ソースを参照

compiles the example server, but crashes

Julius Pfrommer 9 年 前
コミット
bd1ebce5f3

+ 1 - 2
examples/logger_stdout.c

@@ -16,8 +16,7 @@ const char *LogCategoryNames[6] = {"network", "channel", "session", "server", "c
 #endif
 
 void Logger_Stdout(UA_LogLevel level, UA_LogCategory category, const char *msg, ...) {
-	UA_String time;
-	UA_DateTime_toString(UA_DateTime_now(), &time);
+	UA_String time = UA_DateTime_toString(UA_DateTime_now());
     printf("[%.23s] %s/%s\t", time.data, LogLevelNames[level], LogCategoryNames[category]);
 	UA_ByteString_deleteMembers(&time);
     va_list ap;

+ 8 - 2
examples/networklayer_tcp.c

@@ -200,7 +200,10 @@ static UA_StatusCode
 ServerNetworkLayerGetSendBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
     if(length > connection->remoteConf.recvBufferSize)
         return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    return UA_ByteString_newMembers(buf, length);
+    *buf = UA_ByteString_withSize(length);
+    if(buf->data == NULL)
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+    return UA_STATUSCODE_GOOD;
 }
 
 static void
@@ -456,7 +459,10 @@ ClientNetworkLayerGetBuffer(UA_Connection *connection, size_t length, UA_ByteStr
         return UA_STATUSCODE_BADCOMMUNICATIONERROR;
     if(connection->state == UA_CONNECTION_CLOSED)
         return UA_STATUSCODE_BADCONNECTIONCLOSED;
-    return UA_ByteString_newMembers(buf, connection->remoteConf.recvBufferSize);
+    *buf = UA_ByteString_withSize(connection->remoteConf.recvBufferSize);
+    if(buf->data == NULL)
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+    return UA_STATUSCODE_GOOD;
 }
 
 static void

+ 4 - 4
examples/server.c

@@ -337,7 +337,7 @@ int main(int argc, char** argv) {
                             UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL);
 
     UA_UInt32 id = 51000; // running id in namespace 0
-    for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
+    for(UA_UInt32 type = 0; type < UA_TYPES_DIAGNOSTICINFO; type++) {
         if(type == UA_TYPES_VARIANT || type == UA_TYPES_DIAGNOSTICINFO)
             continue;
 
@@ -358,7 +358,7 @@ int main(int argc, char** argv) {
         UA_Variant_deleteMembers(&attr.value);
 
         /* add an array node for every built-in type */
-        UA_Variant_setArray(&attr.value, UA_Array_new(&UA_TYPES[type], 10),
+        UA_Variant_setArray(&attr.value, UA_Array_new(10, &UA_TYPES[type]),
                             10, &UA_TYPES[type]);
         UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id),
                                   UA_NODEID_NUMERIC(1, ARRAYID),
@@ -367,8 +367,8 @@ int main(int argc, char** argv) {
         UA_Variant_deleteMembers(&attr.value);
 
         /* add an matrix node for every built-in type */
-        void* myMultiArray = UA_Array_new(&UA_TYPES[type],9);
-        attr.value.arrayDimensions = UA_Array_new(&UA_TYPES[UA_TYPES_INT32],2);
+        void* myMultiArray = UA_Array_new(9, &UA_TYPES[type]);
+        attr.value.arrayDimensions = UA_Array_new(2, &UA_TYPES[UA_TYPES_INT32]);
         attr.value.arrayDimensions[0] = 3;
         attr.value.arrayDimensions[1] = 3;
         attr.value.arrayDimensionsSize = 2;

+ 351 - 319
include/ua_types.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 the contributors as stated in the AUTHORS file
+ * Copyright (C) 2013-2015 the contributors as stated in the AUTHORS file
  *
  * This file is part of open62541. open62541 is free software: you can
  * redistribute it and/or modify it under the terms of the GNU Lesser General
@@ -28,6 +28,15 @@ extern "C" {
 #include "ua_config.h"
 #include "ua_statuscodes.h"
 
+/* Indicates that an array has the length 0 (NULL indicates an non-defined array of length -1)*/
+#define UA_EMPTY_ARRAY_SENTINEL ((void*)0x01)
+
+/****************************/
+/* Builtin Type Definitions */
+/****************************/
+
+#define UA_BUILTIN_TYPES_COUNT 25
+
 /** A two-state logical value (true or false). */
 typedef bool UA_Boolean;
 #define UA_TRUE true
@@ -81,7 +90,7 @@ typedef double UA_Double;
 
 /** A sequence of Unicode characters. */
 typedef struct {
-    UA_Int32 length; ///< The length of the string
+    size_t length; ///< The length of the string
     UA_Byte *data; ///< The string's content (not null-terminated)
 } UA_String;
 
@@ -104,7 +113,7 @@ typedef UA_String UA_ByteString;
 typedef UA_String UA_XmlElement;
 
 enum UA_NodeIdType {
-    UA_NODEIDTYPE_NUMERIC    = 2,
+    UA_NODEIDTYPE_NUMERIC    = 0, ///< On the wire, this can be 0,1,2 for numeric nodeids of different sizes
     UA_NODEIDTYPE_STRING     = 3,
     UA_NODEIDTYPE_GUID       = 4,
     UA_NODEIDTYPE_BYTESTRING = 5
@@ -113,21 +122,21 @@ enum UA_NodeIdType {
 /** An identifier for a node in the address space of an OPC UA Server. The shortened numeric types
     are introduced during encoding. */
 typedef struct {
-    UA_UInt16 namespaceIndex; ///< The namespace index of the node
-    enum UA_NodeIdType identifierType; ///< The type of the node identifier
+    UA_UInt16 namespaceIndex;
+    enum UA_NodeIdType identifierType;
     union {
         UA_UInt32     numeric;
         UA_String     string;
         UA_Guid       guid;
         UA_ByteString byteString;
-    } identifier; ///< The node identifier
+    } identifier;
 } UA_NodeId;
 
 /** A NodeId that allows the namespace URI to be specified instead of an index. */
 typedef struct {
-    UA_NodeId nodeId; ///< The nodeid without extensions
-    UA_String namespaceUri; ///< The Uri of the namespace (tindex in the nodeId is ignored)
-    UA_UInt32 serverIndex;  ///< The index of the server
+    UA_NodeId nodeId;
+    UA_String namespaceUri;
+    UA_UInt32 serverIndex;
 } UA_ExpandedNodeId;
 
 /** A name qualified by a namespace. */
@@ -142,29 +151,38 @@ typedef struct {
     UA_String text; ///< The actual text
 } UA_LocalizedText;
 
-/** A structure that contains an application specific data type that may not be recognized by the
-    receiver. */
-typedef struct {
-    UA_NodeId typeId; ///< The nodeid of the datatype
-    enum {
-        UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED  = 0,
-        UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING = 1,
-        UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML        = 2
-    } encoding; ///< The encoding of the contained data
-    UA_ByteString body; ///< The bytestring of the encoded data
-} UA_ExtensionObject;
-
 /* Forward Declaration of UA_DataType */
 struct UA_DataType;
 typedef struct UA_DataType UA_DataType; 
 
+/** A structure that contains an application specific data type that may not be recognized by the receiver. */
+typedef struct {
+    enum {
+        UA_EXTENSIONOBJECT_ENCODED_NOBODY     = 0,
+        UA_EXTENSIONOBJECT_ENCODED_BYTESTRING = 1,
+        UA_EXTENSIONOBJECT_ENCODED_XML        = 2,
+        UA_EXTENSIONOBJECT_DECODED            = 3, ///< There is a pointer to the decoded data
+        UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4  ///< Don't delete the decoded data at the lifecycle end
+    } encoding;
+    union {
+        struct {
+            UA_NodeId typeId; ///< The nodeid of the datatype
+            UA_ByteString body; ///< The bytestring of the encoded data
+        } encoded;
+        struct {
+            const UA_DataType *type;
+            void *data;
+        } decoded;
+    } content;
+} UA_ExtensionObject;
+
 /* NumericRanges are used select a subset in a (multidimensional) variant array.
  * NumericRange has no official type structure in the standard. On the wire, it
  * only exists as an encoded string, such as "1:2,0:3,5". The colon separates
  * min/max index and the comma separates dimensions. A single value indicates a
  * range with a single element (min==max). */
 typedef struct {
-    UA_Int32 dimensionsSize;
+    size_t dimensionsSize;
     struct UA_NumericRangeDimension {
         UA_UInt32 min;
         UA_UInt32 max;
@@ -176,10 +194,10 @@ typedef struct {
  *   the data they store (exception: use a data source).
  *
  * Variant semantics:
- *  - arrayLength = -1 && data == NULL: empty variant
- *  - arrayLength = -1 && data == !NULL: variant holds a single element (a scalar)
- *  - arrayLength >= 0: variant holds an array of the appropriate length
- *                      data can be NULL if arrayLength == 0
+ *  - arrayLength == 0 && data == NULL: no existing data
+ *  - arrayLength == 0 && data == 0x01: array of length 0
+ *  - arrayLength == 0 && data > 0x01: scalar value
+ *  - arrayLength > 0: array of the given length
  */
 typedef struct {
     const UA_DataType *type; ///< The nodeid of the datatype
@@ -190,18 +208,18 @@ typedef struct {
                                        possible to overwrite borrowed data due to concurrent access.
                                        Use a custom datasource with a mutex. */
     } storageType; ///< Shall the data be deleted together with the variant
-    UA_Int32  arrayLength;  ///< the number of elements in the data-pointer
-    void     *data; ///< points to the scalar or array data
-    UA_Int32  arrayDimensionsSize; ///< the number of dimensions the data-array has
-    UA_Int32 *arrayDimensions; ///< the length of each dimension of the data-array
+    size_t arrayLength;  ///< the number of elements in the data-pointer
+    void *data; ///< points to the scalar or array data
+    size_t arrayDimensionsSize; ///< the number of dimensions the data-array has
+    UA_UInt32 *arrayDimensions; ///< the length of each dimension of the data-array
 } UA_Variant;
 
 /** A data value with an associated status code and timestamps. */
 typedef struct {
-    UA_Boolean    hasValue : 1;
-    UA_Boolean    hasStatus : 1;
-    UA_Boolean    hasSourceTimestamp : 1;
-    UA_Boolean    hasServerTimestamp : 1;
+    UA_Boolean    hasValue             : 1;
+    UA_Boolean    hasStatus            : 1;
+    UA_Boolean    hasSourceTimestamp   : 1;
+    UA_Boolean    hasServerTimestamp   : 1;
     UA_Boolean    hasSourcePicoseconds : 1;
     UA_Boolean    hasServerPicoseconds : 1;
     UA_Variant    value;
@@ -214,12 +232,12 @@ typedef struct {
 
 /** A structure that contains detailed error and diagnostic information associated with a StatusCode. */
 typedef struct UA_DiagnosticInfo {
-    UA_Boolean    hasSymbolicId : 1;
-    UA_Boolean    hasNamespaceUri : 1;
-    UA_Boolean    hasLocalizedText : 1;
-    UA_Boolean    hasLocale : 1;
-    UA_Boolean    hasAdditionalInfo : 1;
-    UA_Boolean    hasInnerStatusCode : 1;
+    UA_Boolean    hasSymbolicId          : 1;
+    UA_Boolean    hasNamespaceUri        : 1;
+    UA_Boolean    hasLocalizedText       : 1;
+    UA_Boolean    hasLocale              : 1;
+    UA_Boolean    hasAdditionalInfo      : 1;
+    UA_Boolean    hasInnerStatusCode     : 1;
     UA_Boolean    hasInnerDiagnosticInfo : 1;
     UA_Int32      symbolicId;
     UA_Int32      namespaceUri;
@@ -230,123 +248,237 @@ typedef struct UA_DiagnosticInfo {
     struct UA_DiagnosticInfo *innerDiagnosticInfo;
 } UA_DiagnosticInfo;
 
-/***************************/
-/* Type Handling Functions */
-/***************************/
+/*************************/
+/* Generic Type Handling */
+/*************************/
+
+#define UA_MAX_TYPE_MEMBERS 13 // Maximum number of members per structured type
+
+typedef struct {
+#ifdef ENABLE_TYPEINTROSPECTION
+    const char *memberName;
+#endif
+    UA_UInt16   memberTypeIndex;   ///< Index of the member in the datatypetable
+    UA_Byte     padding;           /**< How much padding is there before this member element? For arrays this is
+                                        split into 2 bytes padding before the length index (max 4 bytes) and 3
+                                        bytes padding before the pointer (max 8 bytes) */
+    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_Boolean  isArray       : 1; ///< The member is an array of the given type
+} UA_DataTypeMember;
+    
+struct UA_DataType {
+#ifdef ENABLE_TYPEINTROSPECTION
+    const char *typeName;
+#endif
+    UA_NodeId   typeId;           ///< The nodeid of the type
+    UA_UInt16   memSize;          ///< Size of the struct in memory
+    UA_UInt16   typeIndex;        ///< Index of the type in the datatypetable
+    UA_Byte     membersSize;      ///< How many members does the type have?
+    UA_Boolean  builtin      : 1; ///< The type is "builtin" and has dedicated de- and encoding functions
+    UA_Boolean  fixedSize    : 1; ///< The type (and its members) contains no pointers
+    UA_Boolean  zeroCopyable : 1; ///< The type can be copied directly off the stream (given that the endianness matches)
+    UA_DataTypeMember members[UA_MAX_TYPE_MEMBERS];
+};
+
+/**
+ * Allocates and initializes a variable of type dataType
+ *
+ * @param type The datatype description
+ * @return Returns the memory location of the variable or (void*)0 if no memory is available
+ */
+void UA_EXPORT * UA_new(const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
+
+/**
+ * Initializes a variable to default values
+ *
+ * @param p The memory location of the variable
+ * @param type The datatype description
+ */
+void UA_EXPORT UA_init(void *p, const UA_DataType *type);
+
+/**
+ * Copies the content of two variables. If copying fails (e.g. because no memory was available for
+ * an array), then dst is emptied and initialized to prevent memory leaks.
+ *
+ * @param src The memory location of the source variable
+ * @param dst The memory location of the destination variable
+ * @param type The datatype description
+ * @return Indicates whether the operation succeeded or returns an error code
+ */
+UA_StatusCode UA_EXPORT
+UA_copy(const void *src, void *dst, const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/**
+ * Deletes the dynamically assigned content of a variable (e.g. a member-array).
+ * Afterwards, the variable can be safely deleted without causing memory leaks.
+ * But the variable is not initialized and may contain old data that is not
+ * memory-relevant.
+ *
+ * @param p The memory location of the variable
+ * @param type The datatype description of the variable
+ */
+void UA_EXPORT UA_deleteMembers(void *p, const UA_DataType *type);
+
+/**
+ * Deletes (frees) a variable and all of its content.
+ *
+ * @param p The memory location of the variable
+ * @param type The datatype description of the variable
+ */
+void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
+
+/********************/
+/* Array operations */
+/********************/
+
+#define MAX_ARRAY_SIZE 104857600 // arrays must be smaller than 100MB
+
+/**
+ * Allocates and initializes an array of variables of a specific type
+ *
+ * @param size The requested array length
+ * @param type The datatype description
+ * @return Returns the memory location of the variable or (void*)0 if no memory could be allocated
+ */
+void UA_EXPORT * UA_Array_new(size_t size, const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
+
+/**
+ * Allocates and copies an array. dst is set to (void*)0 if not enough memory is available.
+ *
+ * @param src The memory location of the source array
+ * @param src_size The size of the array
+ * @param dst The location of the pointer to the new array
+ * @param type The datatype of the array members
+ * @return Returns whether copying succeeded
+ */
+UA_StatusCode UA_EXPORT
+UA_Array_copy(const void *src, size_t src_size, void **dst,
+              const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/**
+ * Deletes an array.
+ *
+ * @param p The memory location of the array
+ * @param size The size of the array
+ * @param type The datatype of the array members
+ */
+void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
+
+/***********************************/
+/* Builtin Type Handling Functions */
+/***********************************/
+
+#include "ua_types_generated.h"
 
 /* Boolean */
-UA_Boolean UA_EXPORT * UA_Boolean_new(void);
+static UA_INLINE UA_Boolean * UA_Boolean_new(void) { return UA_new(&UA_TYPES[UA_TYPES_BOOLEAN]); }
 static UA_INLINE void UA_Boolean_init(UA_Boolean *p) { *p = UA_FALSE; }
-void UA_EXPORT UA_Boolean_delete(UA_Boolean *p);
+static UA_INLINE void UA_Boolean_delete(UA_Boolean *p) { UA_delete(p, &UA_TYPES[UA_TYPES_BOOLEAN]); }
 static UA_INLINE void UA_Boolean_deleteMembers(UA_Boolean *p) { }
-static UA_INLINE UA_StatusCode UA_Boolean_copy(const UA_Boolean *src, UA_Boolean *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Boolean_copy(const UA_Boolean *src, UA_Boolean *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* SByte */
-UA_SByte UA_EXPORT * UA_SByte_new(void);
+static UA_INLINE UA_SByte * UA_SByte_new(void) { return UA_new(&UA_TYPES[UA_TYPES_SBYTE]); }
 static UA_INLINE void UA_SByte_init(UA_SByte *p) { *p = 0; }
-void UA_EXPORT UA_SByte_delete(UA_SByte *p);
+static UA_INLINE void UA_SByte_delete(UA_SByte *p) { UA_delete(p, &UA_TYPES[UA_TYPES_SBYTE]); }
 static UA_INLINE void UA_SByte_deleteMembers(UA_SByte *p) { }
-static UA_INLINE UA_StatusCode UA_SByte_copy(const UA_SByte *src, UA_SByte *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_SByte_copy(const UA_SByte *src, UA_SByte *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Byte */
-UA_Byte UA_EXPORT * UA_Byte_new(void);
+static UA_INLINE UA_Byte * UA_Byte_new(void) { return UA_new(&UA_TYPES[UA_TYPES_BYTE]); }
 static UA_INLINE void UA_Byte_init(UA_Byte *p) { *p = 0; }
-void UA_EXPORT UA_Byte_delete(UA_Byte *p);
+static UA_INLINE void UA_Byte_delete(UA_Byte *p) { UA_delete(p, &UA_TYPES[UA_TYPES_BYTE]); }
 static UA_INLINE void UA_Byte_deleteMembers(UA_Byte *p) { }
-static UA_INLINE UA_StatusCode UA_Byte_copy(const UA_Byte *src, UA_Byte *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Byte_copy(const UA_Byte *src, UA_Byte *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Int16 */
-UA_Int16 UA_EXPORT * UA_Int16_new(void);
+static UA_INLINE UA_Int16 * UA_Int16_new(void) { return UA_new(&UA_TYPES[UA_TYPES_INT16]); }
 static UA_INLINE void UA_Int16_init(UA_Int16 *p) { *p = 0; }
-void UA_EXPORT UA_Int16_delete(UA_Int16 *p);
+static UA_INLINE void UA_Int16_delete(UA_Int16 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_INT16]); }
 static UA_INLINE void UA_Int16_deleteMembers(UA_Int16 *p) { }
-static UA_INLINE UA_StatusCode UA_Int16_copy(const UA_Int16 *src, UA_Int16 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Int16_copy(const UA_Int16 *src, UA_Int16 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* UInt16 */
-UA_UInt16 UA_EXPORT * UA_UInt16_new(void);
+static UA_INLINE UA_UInt16 * UA_UInt16_new(void) { return UA_new(&UA_TYPES[UA_TYPES_UINT16]); }
 static UA_INLINE void UA_UInt16_init(UA_UInt16 *p) { *p = 0; }
-void UA_EXPORT UA_UInt16_delete(UA_UInt16 *p);
+static UA_INLINE void UA_UInt16_delete(UA_UInt16 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_UINT16]); }
 static UA_INLINE void UA_UInt16_deleteMembers(UA_UInt16 *p) { }
-static UA_INLINE UA_StatusCode UA_UInt16_copy(const UA_UInt16 *src, UA_UInt16 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_UInt16_copy(const UA_UInt16 *src, UA_UInt16 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Int32 */
-UA_Int32 UA_EXPORT * UA_Int32_new(void);
+static UA_INLINE UA_Int32 * UA_Int32_new(void) { return UA_new(&UA_TYPES[UA_TYPES_INT32]); }
 static UA_INLINE void UA_Int32_init(UA_Int32 *p) { *p = 0; }
-void UA_EXPORT UA_Int32_delete(UA_Int32 *p);
+static UA_INLINE void UA_Int32_delete(UA_Int32 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_INT32]); }
 static UA_INLINE void UA_Int32_deleteMembers(UA_Int32 *p) { }
-static UA_INLINE UA_StatusCode UA_Int32_copy(const UA_Int32 *src, UA_Int32 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Int32_copy(const UA_Int32 *src, UA_Int32 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* UInt32 */
-UA_UInt32 UA_EXPORT * UA_UInt32_new(void);
+static UA_INLINE UA_UInt32 * UA_UInt32_new(void) { return UA_new(&UA_TYPES[UA_TYPES_UINT32]); }
 static UA_INLINE void UA_UInt32_init(UA_UInt32 *p) { *p = 0; }
-void UA_EXPORT UA_UInt32_delete(UA_UInt32 *p);
+static UA_INLINE void UA_UInt32_delete(UA_UInt32 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_UINT32]); }
 static UA_INLINE void UA_UInt32_deleteMembers(UA_UInt32 *p) { }
-static UA_INLINE UA_StatusCode UA_UInt32_copy(const UA_UInt32 *src, UA_UInt32 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_UInt32_copy(const UA_UInt32 *src, UA_UInt32 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Int64 */
-UA_Int64 UA_EXPORT * UA_Int64_new(void);
+static UA_INLINE UA_Int64 * UA_Int64_new(void) { return UA_new(&UA_TYPES[UA_TYPES_INT64]); }
 static UA_INLINE void UA_Int64_init(UA_Int64 *p) { *p = 0; }
-void UA_EXPORT UA_Int64_delete(UA_Int64 *p);
+static UA_INLINE void UA_Int64_delete(UA_Int64 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_INT64]); }
 static UA_INLINE void UA_Int64_deleteMembers(UA_Int64 *p) { }
-static UA_INLINE UA_StatusCode UA_Int64_copy(const UA_Int64 *src, UA_Int64 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Int64_copy(const UA_Int64 *src, UA_Int64 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* UInt64 */
-UA_UInt64 UA_EXPORT * UA_UInt64_new(void);
+static UA_INLINE UA_UInt64 * UA_UInt64_new(void) { return UA_new(&UA_TYPES[UA_TYPES_UINT64]); }
 static UA_INLINE void UA_UInt64_init(UA_UInt64 *p) { *p = 0; }
-void UA_EXPORT UA_UInt64_delete(UA_UInt64 *p);
+static UA_INLINE void UA_UInt64_delete(UA_UInt64 *p) { UA_delete(p, &UA_TYPES[UA_TYPES_UINT64]); }
 static UA_INLINE void UA_UInt64_deleteMembers(UA_UInt64 *p) { }
-static UA_INLINE UA_StatusCode UA_UInt64_copy(const UA_UInt64 *src, UA_UInt64 *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_UInt64_copy(const UA_UInt64 *src, UA_UInt64 *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Float */
-UA_Float UA_EXPORT * UA_Float_new(void);
+static UA_INLINE UA_Float * UA_Float_new(void) { return UA_new(&UA_TYPES[UA_TYPES_FLOAT]); }
 static UA_INLINE void UA_Float_init(UA_Float *p) { *p = 0.0f; }
-void UA_EXPORT UA_Float_delete(UA_Float *p);
+static UA_INLINE void UA_Float_delete(UA_Float *p) { UA_delete(p, &UA_TYPES[UA_TYPES_FLOAT]); }
 static UA_INLINE void UA_Float_deleteMembers(UA_Float *p) { }
-static UA_INLINE UA_StatusCode UA_Float_copy(const UA_Float *src, UA_Float *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Float_copy(const UA_Float *src, UA_Float *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* Double */
-UA_Double UA_EXPORT * UA_Double_new(void);
+static UA_INLINE UA_Double * UA_Double_new(void) { return UA_new(&UA_TYPES[UA_TYPES_DOUBLE]); }
 static UA_INLINE void UA_Double_init(UA_Double *p) { *p = 0.0f; }
-void UA_EXPORT UA_Double_delete(UA_Double *p);
+static UA_INLINE void UA_Double_delete(UA_Double *p) { UA_delete(p, &UA_TYPES[UA_TYPES_DOUBLE]); }
 static UA_INLINE void UA_Double_deleteMembers(UA_Double *p) { }
-static UA_INLINE UA_StatusCode UA_Double_copy(const UA_Double *src, UA_Double *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Double_copy(const UA_Double *src, UA_Double *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* String */
-UA_String UA_EXPORT * UA_String_new(void);
-void UA_EXPORT UA_String_init(UA_String *p);
-void UA_EXPORT UA_String_delete(UA_String *p);
-void UA_EXPORT UA_String_deleteMembers(UA_String *p);
-UA_StatusCode UA_EXPORT UA_String_copy(const UA_String *src, UA_String *dst);
-UA_String UA_EXPORT UA_String_fromChars(char const src[]); ///> Copies the content on the heap. Returns a null-string when alloc fails.
-UA_Boolean UA_EXPORT UA_String_equal(const UA_String *s1, const UA_String *s2); ///> Compares two strings
+static UA_INLINE UA_String * UA_String_new(void) { return UA_new(&UA_TYPES[UA_TYPES_STRING]); }
+static UA_INLINE void UA_String_init(UA_String *p) { memset(p, 0, sizeof(UA_String)); }
+static UA_INLINE void UA_String_delete(UA_String *p) { UA_delete(p, &UA_TYPES[UA_TYPES_STRING]); }
+static UA_INLINE void UA_String_deleteMembers(UA_String *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_STRING]); }
+static UA_INLINE UA_StatusCode UA_String_copy(const UA_String *src, UA_String *dst) {return UA_copy(src, dst, &UA_TYPES[UA_TYPES_STRING]); }
+
+/** Copies the content on the heap. Returns a null-string when alloc fails */
+UA_String UA_EXPORT UA_String_fromChars(char const src[]);
+
+UA_Boolean UA_EXPORT UA_String_equal(const UA_String *s1, const UA_String *s2);
+
 UA_EXPORT extern const UA_String UA_STRING_NULL;
+
 static UA_INLINE UA_String UA_STRING(char *chars) {
     UA_String str;
     str.length = strlen(chars);
-    str.data = (UA_Byte*)chars;
+    str.data   = (UA_Byte*)chars;
     return str; }
+
 #define UA_STRING_ALLOC(CHARS) UA_String_fromChars(CHARS)
 
 /* DateTime */
-UA_DateTime UA_EXPORT * UA_DateTime_new(void);
-static UA_INLINE void UA_DateTime_init(UA_DateTime *p) { *p = (UA_DateTime)0.0f; }
-void UA_EXPORT UA_DateTime_delete(UA_DateTime *p);
+static UA_INLINE UA_DateTime * UA_DateTime_new(void) { return UA_new(&UA_TYPES[UA_TYPES_DATETIME]); }
+static UA_INLINE void UA_DateTime_init(UA_DateTime *p) { *p = 0; }
+static UA_INLINE void UA_DateTime_delete(UA_DateTime *p) { UA_delete(p, &UA_TYPES[UA_TYPES_DATETIME]); }
 static UA_INLINE void UA_DateTime_deleteMembers(UA_DateTime *p) { }
-static UA_INLINE UA_StatusCode UA_DateTime_copy(const UA_DateTime *src, UA_DateTime *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_DateTime_copy(const UA_DateTime *src, UA_DateTime *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
+
 UA_DateTime UA_EXPORT UA_DateTime_now(void); ///> The current time
-UA_StatusCode UA_EXPORT UA_DateTime_toString(UA_DateTime time, UA_String *timeString);
 
 typedef struct UA_DateTimeStruct {
     UA_UInt16 nanoSec;
@@ -362,97 +494,106 @@ typedef struct UA_DateTimeStruct {
 
 UA_DateTimeStruct UA_EXPORT UA_DateTime_toStruct(UA_DateTime time);
 
+UA_String UA_EXPORT UA_DateTime_toString(UA_DateTime time);
+
 /* Guid */
-UA_Guid UA_EXPORT * UA_Guid_new(void);
+static UA_INLINE UA_Guid * UA_Guid_new(void) { return UA_new(&UA_TYPES[UA_TYPES_GUID]); }
 static UA_INLINE void UA_Guid_init(UA_Guid *p) { memset(p, 0, sizeof(UA_Guid)); }
-void UA_EXPORT UA_Guid_delete(UA_Guid *p);
+static UA_INLINE void UA_Guid_delete(UA_Guid *p) { UA_delete(p, &UA_TYPES[UA_TYPES_GUID]); }
 static UA_INLINE void UA_Guid_deleteMembers(UA_Guid *p) { }
-static UA_INLINE UA_StatusCode UA_Guid_copy(const UA_Guid *src, UA_Guid *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_Guid_copy(const UA_Guid *src, UA_Guid *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
+
 UA_Boolean UA_EXPORT UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2);
-UA_Guid UA_EXPORT UA_Guid_random(UA_UInt32 *seed); ///> Do not use for security-critical entropy!
+
+UA_Guid UA_EXPORT UA_Guid_random(UA_UInt32 *seed);
 
 /* ByteString */
-static UA_INLINE UA_ByteString * UA_ByteString_new(void) { return UA_String_new(); }
-static UA_INLINE void UA_ByteString_init(UA_ByteString *p) { UA_String_init(p); }
-static UA_INLINE void UA_ByteString_delete(UA_ByteString *p) { UA_String_delete(p); }
-static UA_INLINE void UA_ByteString_deleteMembers(UA_ByteString *p) { UA_String_deleteMembers(p); }
-static UA_INLINE UA_StatusCode UA_ByteString_copy(const UA_ByteString *src, UA_ByteString *dst) {
-    return UA_String_copy(src, dst); }
-#define UA_ByteString_equal(string1, string2) UA_String_equal((const UA_String*) string1, (const UA_String*)string2)
+static UA_INLINE UA_ByteString * UA_ByteString_new(void) { return UA_new(&UA_TYPES[UA_TYPES_BYTESTRING]); }
+static UA_INLINE void UA_ByteString_init(UA_ByteString *p) { memset(p, 0, sizeof(UA_ByteString)); }
+static UA_INLINE void UA_ByteString_delete(UA_ByteString *p) { UA_delete(p, &UA_TYPES[UA_TYPES_BYTESTRING]); }
+static UA_INLINE void UA_ByteString_deleteMembers(UA_ByteString *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_BYTESTRING]); }
+static UA_INLINE UA_StatusCode UA_ByteString_copy(const UA_ByteString *src, UA_ByteString *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_BYTESTRING]); }
+
+static UA_INLINE 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); }
+
 /* Allocates memory of size length for the bytestring. The content is not set to zero. */
-UA_StatusCode UA_EXPORT UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length);
+UA_ByteString UA_EXPORT UA_ByteString_withSize(size_t length);
+
 UA_EXPORT extern const UA_ByteString UA_BYTESTRING_NULL;
+
 static UA_INLINE UA_ByteString UA_BYTESTRING(char *chars) {
     UA_ByteString str;
     str.length = strlen(chars);
-    str.data = (UA_Byte*)chars;
+    str.data   = (UA_Byte*)chars;
     return str; }
+
 static UA_INLINE UA_ByteString UA_BYTESTRING_ALLOC(const char *chars) {
     UA_String str = UA_String_fromChars(chars);
     UA_ByteString bstr;
     bstr.length = str.length;
-    bstr.data = str.data;
+    bstr.data   = str.data;
     return bstr;
 }
 
 /* XmlElement */
-static UA_INLINE UA_XmlElement * UA_XmlElement_new(void) { return UA_String_new(); }
-static UA_INLINE void UA_XmlElement_init(UA_XmlElement *p) { UA_String_init(p); }
-static UA_INLINE void UA_XmlElement_delete(UA_XmlElement *p) { UA_String_delete(p); }
-static UA_INLINE void UA_XmlElement_deleteMembers(UA_XmlElement *p) { UA_String_deleteMembers(p); }
-static UA_INLINE UA_StatusCode UA_XmlElement_copy(const UA_XmlElement *src, UA_XmlElement *dst) {
-    return UA_String_copy(src, dst); }
+static UA_INLINE UA_XmlElement * UA_XmlElement_new(void) { return UA_new(&UA_TYPES[UA_TYPES_XMLELEMENT]); }
+static UA_INLINE void UA_XmlElement_init(UA_XmlElement *p) { memset(p, 0, sizeof(UA_XmlElement)); }
+static UA_INLINE void UA_XmlElement_delete(UA_XmlElement *p) { UA_delete(p, &UA_TYPES[UA_TYPES_XMLELEMENT]); }
+static UA_INLINE void UA_XmlElement_deleteMembers(UA_XmlElement *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_XMLELEMENT]); }
+static UA_INLINE UA_StatusCode UA_XmlElement_copy(const UA_XmlElement *src, UA_XmlElement *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_XMLELEMENT]); }
 
 /* NodeId */
-UA_NodeId UA_EXPORT * UA_NodeId_new(void);
-void UA_EXPORT UA_NodeId_init(UA_NodeId *p);
-void UA_EXPORT UA_NodeId_delete(UA_NodeId *p);
-void UA_EXPORT UA_NodeId_deleteMembers(UA_NodeId *p);
-UA_StatusCode UA_EXPORT UA_NodeId_copy(const UA_NodeId *src, UA_NodeId *dst);
+static UA_INLINE UA_NodeId * UA_NodeId_new(void) { return UA_new(&UA_TYPES[UA_TYPES_NODEID]); }
+static UA_INLINE void UA_NodeId_init(UA_NodeId *p) { memset(p, 0, sizeof(UA_NodeId)); }
+static UA_INLINE void UA_NodeId_delete(UA_NodeId *p) { UA_delete(p, &UA_TYPES[UA_TYPES_NODEID]); }
+static UA_INLINE void UA_NodeId_deleteMembers(UA_NodeId *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_NODEID]); }
+static UA_INLINE UA_StatusCode UA_NodeId_copy(const UA_NodeId *src, UA_NodeId *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_NODEID]); }
+
 UA_Boolean UA_EXPORT UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2);
-UA_Boolean UA_EXPORT UA_NodeId_isNull(const UA_NodeId *p);
-UA_NodeId UA_EXPORT UA_NodeId_fromInteger(UA_UInt16 nsIndex, UA_Int32 identifier);
-UA_NodeId UA_EXPORT UA_NodeId_fromCharString(UA_UInt16 nsIndex, char identifier[]);
-UA_NodeId UA_EXPORT UA_NodeId_fromCharStringCopy(UA_UInt16 nsIndex, char const identifier[]);
-UA_NodeId UA_EXPORT UA_NodeId_fromString(UA_UInt16 nsIndex, UA_String identifier);
-UA_NodeId UA_EXPORT UA_NodeId_fromStringCopy(UA_UInt16 nsIndex, UA_String identifier);
-UA_NodeId UA_EXPORT UA_NodeId_fromGuid(UA_UInt16 nsIndex, UA_Guid identifier);
-UA_NodeId UA_EXPORT UA_NodeId_fromCharByteString(UA_UInt16 nsIndex, char identifier[]);
-UA_NodeId UA_EXPORT UA_NodeId_fromCharByteStringCopy(UA_UInt16 nsIndex, char const identifier[]);
-UA_NodeId UA_EXPORT UA_NodeId_fromByteString(UA_UInt16 nsIndex, UA_ByteString identifier);
-UA_NodeId UA_EXPORT UA_NodeId_fromByteStringCopy(UA_UInt16 nsIndex, UA_ByteString identifier);
+
+static UA_INLINE UA_Boolean UA_NodeId_isNull(const UA_NodeId *p) {
+    return (p->namespaceIndex == 0 && p->identifierType == UA_NODEIDTYPE_NUMERIC &&
+            p->identifier.numeric == 0);
+}
+
 UA_EXPORT extern const UA_NodeId UA_NODEID_NULL;
+
 static UA_INLINE UA_NodeId UA_NODEID_NUMERIC(UA_UInt16 nsIndex, UA_Int32 identifier) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
     id.identifierType = UA_NODEIDTYPE_NUMERIC;
     id.identifier.numeric = identifier;
     return id; }
+
 static UA_INLINE UA_NodeId UA_NODEID_STRING(UA_UInt16 nsIndex, char *chars) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
     id.identifierType = UA_NODEIDTYPE_STRING;
     id.identifier.string = UA_STRING(chars);
     return id; }
+
 static UA_INLINE UA_NodeId UA_NODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
     id.identifierType = UA_NODEIDTYPE_STRING;
     id.identifier.string = UA_STRING_ALLOC(chars);
     return id; }
+
 static UA_INLINE UA_NodeId UA_NODEID_GUID(UA_UInt16 nsIndex, UA_Guid guid) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
     id.identifierType = UA_NODEIDTYPE_GUID;
     id.identifier.guid = guid;
     return id; }
+
 static UA_INLINE UA_NodeId UA_NODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
     id.identifierType = UA_NODEIDTYPE_BYTESTRING;
     id.identifier.byteString = UA_BYTESTRING(chars);
     return id; }
+
 static UA_INLINE UA_NodeId UA_NODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_NodeId id;
     id.namespaceIndex = nsIndex;
@@ -461,104 +602,112 @@ static UA_INLINE UA_NodeId UA_NODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const c
     return id; }
 
 /* ExpandedNodeId */
-UA_ExpandedNodeId UA_EXPORT * UA_ExpandedNodeId_new(void);
-void UA_EXPORT UA_ExpandedNodeId_init(UA_ExpandedNodeId *p);
-void UA_EXPORT UA_ExpandedNodeId_delete(UA_ExpandedNodeId *p);
-void UA_EXPORT UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p);
-UA_StatusCode UA_EXPORT UA_ExpandedNodeId_copy(const UA_ExpandedNodeId *src, UA_ExpandedNodeId *dst);
-UA_EXPORT extern const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL;
+static UA_INLINE UA_ExpandedNodeId * UA_ExpandedNodeId_new(void) { return UA_new(&UA_TYPES[UA_TYPES_EXPANDEDNODEID]); }
+static UA_INLINE void UA_ExpandedNodeId_init(UA_ExpandedNodeId *p) { memset(p, 0, sizeof(UA_ExpandedNodeId)); }
+static UA_INLINE void UA_ExpandedNodeId_delete(UA_ExpandedNodeId *p) { UA_delete(p, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); }
+static UA_INLINE void UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); }
+static UA_INLINE UA_StatusCode UA_ExpandedNodeId_copy(const UA_ExpandedNodeId *src, UA_ExpandedNodeId *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_NUMERIC(UA_UInt16 nsIndex, UA_Int32 identifier) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_NUMERIC(nsIndex, identifier);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_NUMERIC(nsIndex, identifier);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING(UA_UInt16 nsIndex, char *chars) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_STRING(nsIndex, chars);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_STRING(nsIndex, chars);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_STRING_ALLOC(nsIndex, chars);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_STRING_ALLOC(nsIndex, chars);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_GUID(UA_UInt16 nsIndex, UA_Guid guid) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_GUID(nsIndex, guid);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_GUID(nsIndex, guid);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_BYTESTRING(nsIndex, chars);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_BYTESTRING(nsIndex, chars);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
+
 static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_ExpandedNodeId id;
-    id.nodeId = UA_NODEID_BYTESTRING_ALLOC(nsIndex, chars);
-    id.serverIndex = 0;
+    id.nodeId       = UA_NODEID_BYTESTRING_ALLOC(nsIndex, chars);
+    id.serverIndex  = 0;
     id.namespaceUri = UA_STRING_NULL;
     return id; }
 
 /* StatusCode */
-static UA_INLINE UA_StatusCode * UA_StatusCode_new(void) { return (UA_StatusCode*)UA_Int32_new(); }
+static UA_INLINE UA_StatusCode * UA_StatusCode_new(void) { return UA_new(&UA_TYPES[UA_TYPES_STATUSCODE]); }
 static UA_INLINE void UA_StatusCode_init(UA_StatusCode *p) { *p = UA_STATUSCODE_GOOD; }
-void UA_EXPORT UA_StatusCode_delete(UA_StatusCode *p);
+static UA_INLINE void UA_StatusCode_delete(UA_StatusCode *p) { UA_delete(p, &UA_TYPES[UA_TYPES_STATUSCODE]); }
 static UA_INLINE void UA_StatusCode_deleteMembers(UA_StatusCode *p) { }
-static UA_INLINE UA_StatusCode UA_StatusCode_copy(const UA_StatusCode *src, UA_StatusCode *dst) {
-    *dst = *src; return UA_STATUSCODE_GOOD; }
+static UA_INLINE UA_StatusCode UA_StatusCode_copy(const UA_StatusCode *src, UA_StatusCode *dst) {*dst = *src; return UA_STATUSCODE_GOOD; }
 
 /* QualifiedName */
-UA_QualifiedName UA_EXPORT * UA_QualifiedName_new(void);
-void UA_EXPORT UA_QualifiedName_init(UA_QualifiedName *p);
-void UA_EXPORT UA_QualifiedName_delete(UA_QualifiedName *p);
-void UA_EXPORT UA_QualifiedName_deleteMembers(UA_QualifiedName *p);
-UA_StatusCode UA_EXPORT UA_QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst);
+static UA_INLINE UA_QualifiedName * UA_QualifiedName_new(void) { return UA_new(&UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+static UA_INLINE void UA_QualifiedName_init(UA_QualifiedName *p) { memset(p, 0, sizeof(UA_QualifiedName)); }
+static UA_INLINE void UA_QualifiedName_delete(UA_QualifiedName *p) { UA_delete(p, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+static UA_INLINE void UA_QualifiedName_deleteMembers(UA_QualifiedName *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+static UA_INLINE UA_StatusCode UA_QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+
 static UA_INLINE UA_QualifiedName UA_QUALIFIEDNAME(UA_UInt16 nsIndex, char *chars) {
     UA_QualifiedName qn;
     qn.namespaceIndex = nsIndex;
-    qn.name = UA_STRING(chars);
+    qn.name           = UA_STRING(chars);
     return qn; }
+
 static UA_INLINE UA_QualifiedName UA_QUALIFIEDNAME_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_QualifiedName qn;
     qn.namespaceIndex = nsIndex;
-    qn.name = UA_STRING_ALLOC(chars);
+    qn.name           = UA_STRING_ALLOC(chars);
     return qn; }
 
 /* LocalizedText */
-UA_LocalizedText UA_EXPORT * UA_LocalizedText_new(void);
-void UA_EXPORT UA_LocalizedText_init(UA_LocalizedText *p);
-void UA_EXPORT UA_LocalizedText_delete(UA_LocalizedText *p);
-void UA_EXPORT UA_LocalizedText_deleteMembers(UA_LocalizedText *p);
-UA_StatusCode UA_EXPORT UA_LocalizedText_copy(const UA_LocalizedText *src, UA_LocalizedText *dst);
+static UA_INLINE UA_LocalizedText * UA_LocalizedText_new(void) { return UA_new(&UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+static UA_INLINE void UA_LocalizedText_init(UA_LocalizedText *p) { memset(p, 0, sizeof(UA_LocalizedText)); }
+static UA_INLINE void UA_LocalizedText_delete(UA_LocalizedText *p) { UA_delete(p, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+static UA_INLINE void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+static UA_INLINE UA_StatusCode UA_LocalizedText_copy(const UA_LocalizedText *src, UA_LocalizedText *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
 static UA_INLINE UA_LocalizedText UA_LOCALIZEDTEXT(char *locale, char *text) {
     UA_LocalizedText lt;
     lt.locale = UA_STRING(locale);
-    lt.text = UA_STRING(text);
+    lt.text   = UA_STRING(text);
     return lt; }
+
 static UA_INLINE UA_LocalizedText UA_LOCALIZEDTEXT_ALLOC(const char *locale, const char *text) {
     UA_LocalizedText lt;
     lt.locale = UA_STRING_ALLOC(locale);
-    lt.text = UA_STRING_ALLOC(text);
+    lt.text   = UA_STRING_ALLOC(text);
     return lt; }
 
 /* ExtensionObject */
-UA_ExtensionObject UA_EXPORT * UA_ExtensionObject_new(void);
-void UA_EXPORT UA_ExtensionObject_init(UA_ExtensionObject *p);
-void UA_EXPORT UA_ExtensionObject_delete(UA_ExtensionObject *p);
-void UA_EXPORT UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p);
-UA_StatusCode UA_EXPORT UA_ExtensionObject_copy(const UA_ExtensionObject *src, UA_ExtensionObject *dst);
+static UA_INLINE UA_ExtensionObject * UA_ExtensionObject_new(void) { return UA_new(&UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); }
+static UA_INLINE void UA_ExtensionObject_init(UA_ExtensionObject *p) { memset(p, 0, sizeof(UA_ExtensionObject)); }
+static UA_INLINE void UA_ExtensionObject_delete(UA_ExtensionObject *p) { UA_delete(p, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); }
+static UA_INLINE void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); }
+static UA_INLINE UA_StatusCode UA_ExtensionObject_copy(const UA_ExtensionObject *src, UA_ExtensionObject *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); }
 
 /* Variant */
-UA_Variant UA_EXPORT * UA_Variant_new(void);
-void UA_EXPORT UA_Variant_init(UA_Variant *p);
-void UA_EXPORT UA_Variant_delete(UA_Variant *p);
-void UA_EXPORT UA_Variant_deleteMembers(UA_Variant *p);
-UA_StatusCode UA_EXPORT UA_Variant_copy(const UA_Variant *src, UA_Variant *dst);
+static UA_INLINE UA_Variant * UA_Variant_new(void) { return UA_new(&UA_TYPES[UA_TYPES_VARIANT]); }
+static UA_INLINE void UA_Variant_init(UA_Variant *p) { memset(p, 0, sizeof(UA_Variant)); }
+static UA_INLINE void UA_Variant_delete(UA_Variant *p) { UA_delete(p, &UA_TYPES[UA_TYPES_VARIANT]); }
+static UA_INLINE void UA_Variant_deleteMembers(UA_Variant *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_VARIANT]); }
+static UA_INLINE UA_StatusCode UA_Variant_copy(const UA_Variant *src, UA_Variant *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_VARIANT]); }
 
 /**
  * Returns true if the variant contains a scalar value. Note that empty variants contain an array of
@@ -567,7 +716,8 @@ UA_StatusCode UA_EXPORT UA_Variant_copy(const UA_Variant *src, UA_Variant *dst);
  * @param v The variant
  * @return Does the variant contain a scalar value.
  */
-UA_Boolean UA_EXPORT UA_Variant_isScalar(const UA_Variant *v);
+static UA_INLINE UA_Boolean UA_Variant_isScalar(const UA_Variant *v) {
+    return (v->arrayLength == 0 && v->data >= UA_EMPTY_ARRAY_SENTINEL); }
     
 /**
  * Set the variant to a scalar value that already resides in memory. The value takes on the
@@ -596,24 +746,24 @@ UA_StatusCode UA_EXPORT UA_Variant_setScalarCopy(UA_Variant *v, const void *p, c
  *
  * @param v The variant
  * @param array A pointer to the array data
- * @param elements The size of the array
+ * @param arraySize The size of the array
  * @param type The datatype of the array
  * @return Indicates whether the operation succeeded or returns an error code
  */
 UA_StatusCode UA_EXPORT
-UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array, UA_Int32 elements, const UA_DataType *type);
+UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, const UA_DataType *type);
 
 /**
  * Set the variant to an array that is copied from an existing array.
  *
  * @param v The variant
  * @param array A pointer to the array data
- * @param elements The size of the array
+ * @param arraySize The size of the array
  * @param type The datatype of the array
  * @return Indicates whether the operation succeeded or returns an error code
  */
 UA_StatusCode UA_EXPORT
-UA_Variant_setArrayCopy(UA_Variant *v, const void *array, UA_Int32 elements, const UA_DataType *type);
+UA_Variant_setArrayCopy(UA_Variant *v, const void *array, size_t arraySize, const UA_DataType *type);
 
 /**
  * Copy the variant, but use only a subset of the (multidimensional) array into a variant. Returns
@@ -639,8 +789,7 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRan
  * @return Returns UA_STATUSCODE_GOOD or an error code
  */
 UA_StatusCode UA_EXPORT
-UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT dataArray,
-                    UA_Int32 dataArraySize, const UA_NumericRange range);
+UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, const UA_NumericRange range);
 
 /**
  * Deep-copy a range of data into an existing variant.
@@ -652,138 +801,21 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT dataArray,
  * @return Returns UA_STATUSCODE_GOOD or an error code
  */
 UA_StatusCode UA_EXPORT
-UA_Variant_setRangeCopy(UA_Variant *v, const void *dataArray, UA_Int32 dataArraySize,
-                        const UA_NumericRange range);
+UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize, const UA_NumericRange range);
 
 /* DataValue */
-UA_DataValue UA_EXPORT * UA_DataValue_new(void);
-void UA_EXPORT UA_DataValue_init(UA_DataValue *p);
-void UA_EXPORT UA_DataValue_delete(UA_DataValue *p);
-void UA_EXPORT UA_DataValue_deleteMembers(UA_DataValue *p);
-UA_StatusCode UA_EXPORT UA_DataValue_copy(const UA_DataValue *src, UA_DataValue *dst);
+static UA_INLINE UA_DataValue * UA_DataValue_new(void) { return UA_new(&UA_TYPES[UA_TYPES_DATAVALUE]); }
+static UA_INLINE void UA_DataValue_init(UA_DataValue *p) { memset(p, 0, sizeof(UA_DataValue)); }
+static UA_INLINE void UA_DataValue_delete(UA_DataValue *p) { UA_delete(p, &UA_TYPES[UA_TYPES_DATAVALUE]); }
+static UA_INLINE void UA_DataValue_deleteMembers(UA_DataValue *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_DATAVALUE]); }
+static UA_INLINE UA_StatusCode UA_DataValue_copy(const UA_DataValue *src, UA_DataValue *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DATAVALUE]); }
 
 /* DiagnosticInfo */
-UA_DiagnosticInfo UA_EXPORT * UA_DiagnosticInfo_new(void);
-void UA_EXPORT UA_DiagnosticInfo_init(UA_DiagnosticInfo *p);
-void UA_EXPORT UA_DiagnosticInfo_delete(UA_DiagnosticInfo *p);
-void UA_EXPORT UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p);
-UA_StatusCode UA_EXPORT UA_DiagnosticInfo_copy(const UA_DiagnosticInfo *src, UA_DiagnosticInfo *dst);
-
-/****************************/
-/* Structured Type Handling */
-/****************************/
-
-#define UA_MAX_TYPE_MEMBERS 13 // Maximum number of members per complex type
-
-#define UA_IS_BUILTIN(ID) (ID <= UA_TYPES_DIAGNOSTICINFO)
-
-typedef struct {
-#ifdef ENABLE_TYPEINTROSPECTION
-    const char *memberName;
-#endif
-    UA_UInt16 memberTypeIndex; ///< Index of the member in the datatypetable
-    UA_Byte padding; /**< How much padding is there before this member element? For arrays this is
-                          split into 2 bytes padding before the length index (max 4 bytes) and 3
-                          bytes padding before the pointer (max 8 bytes) */
-    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_Boolean isArray : 1; ///< The member is an array of the given type
-} UA_DataTypeMember;
-    
-struct UA_DataType {
-#ifdef ENABLE_TYPEINTROSPECTION
-    const char *typeName;
-#endif
-    UA_NodeId typeId; ///< The nodeid of the type
-    UA_UInt16 memSize; ///< Size of the struct in memory
-    UA_UInt16 typeIndex; ///< Index of the type in the datatypetable
-    UA_Byte membersSize; ///< How many members does the type have?
-    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_DataTypeMember members[UA_MAX_TYPE_MEMBERS];
-};
-
-/**
- * Allocates and initializes a variable of type dataType
- *
- * @param type The datatype description
- * @return Returns the memory location of the variable or (void*)0 if no memory is available
- */
-void UA_EXPORT * UA_new(const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
-
-/**
- * Initializes a variable to default values
- *
- * @param p The memory location of the variable
- * @param type The datatype description
- */
-void UA_EXPORT UA_init(void *p, const UA_DataType *type);
-
-/**
- * Copies the content of two variables. If copying fails (e.g. because no memory was available for
- * an array), then dst is emptied and initialized to prevent memory leaks.
- *
- * @param src The memory location of the source variable
- * @param dst The memory location of the destination variable
- * @param type The datatype description
- * @return Indicates whether the operation succeeded or returns an error code
- */
-UA_StatusCode UA_EXPORT UA_copy(const void *src, void *dst, const UA_DataType *type);
-
-/**
- * Deletes the dynamically assigned content of a variable (e.g. a member-array). Afterwards, the
- * variable can be safely deleted without causing memory leaks. But the variable is not initialized
- * and may contain old data that is not memory-relevant.
- *
- * @param p The memory location of the variable
- * @param type The datatype description of the variable
- */
-void UA_EXPORT UA_deleteMembers(void *p, const UA_DataType *type);
-
-/**
- * Deletes (frees) a variable and all of its content.
- *
- * @param p The memory location of the variable
- * @param type The datatype description of the variable
- */
-void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
-
-/********************/
-/* Array operations */
-/********************/
-
-#define MAX_ARRAY_SIZE 104857600 // arrays must be smaller than 100MB
-
-/**
- * Allocates and initializes an array of variables of a specific type
- *
- * @param type The datatype description
- * @param elements The number of elements in the array
- * @return Returns the memory location of the variable or (void*)0 if no memory could be allocated
- */
-void UA_EXPORT * UA_Array_new(const UA_DataType *type, UA_Int32 elements) UA_FUNC_ATTR_MALLOC;
-
-/**
- * Allocates and copies an array. dst is set to (void*)0 if not enough memory is available.
- *
- * @param src The memory location of the source array
- * @param dst The memory location where the pointer to the destination array is written
- * @param type The datatype of the array members
- * @param elements The size of the array
- * @return Indicates whether the operation succeeded or returns an error code
- */
-UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, void **dst, const UA_DataType *type, UA_Int32 elements);
-
-/**
- * Deletes an array.
- *
- * @param p The memory location of the array
- * @param type The datatype of the array members
- * @param elements The size of the array
- */
-void UA_EXPORT UA_Array_delete(void *p, const UA_DataType *type, UA_Int32 elements);
+static UA_INLINE UA_DiagnosticInfo * UA_DiagnosticInfo_new(void) { return UA_new(&UA_TYPES[UA_TYPES_DIAGNOSTICINFO]); }
+static UA_INLINE void UA_DiagnosticInfo_init(UA_DiagnosticInfo *p) { memset(p, 0, sizeof(UA_DiagnosticInfo)); }
+static UA_INLINE void UA_DiagnosticInfo_delete(UA_DiagnosticInfo *p) { UA_delete(p, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]); }
+static UA_INLINE void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) { UA_deleteMembers(p, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]); }
+static UA_INLINE UA_StatusCode UA_DiagnosticInfo_copy(const UA_DiagnosticInfo *src, UA_DiagnosticInfo *dst) { return UA_copy(src, dst, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]); }
 
 /**********************/
 /* Node Attribute Ids */

+ 7 - 17
src/client/ua_client.c

@@ -280,22 +280,12 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
 
     UA_AnonymousIdentityToken identityToken;
     UA_AnonymousIdentityToken_init(&identityToken);
-    UA_String_copy(&client->token.policyId, &identityToken.policyId);
+    identityToken.policyId = client->token.policyId,
 
     //manual ExtensionObject encoding of the identityToken
-    request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
-    request.userIdentityToken.typeId = UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN].typeId;
-    request.userIdentityToken.typeId.identifier.numeric+=UA_ENCODINGOFFSET_BINARY;
-    
-    if (identityToken.policyId.length >= 0)
-        UA_ByteString_newMembers(&request.userIdentityToken.body, identityToken.policyId.length+4);
-    else {
-        identityToken.policyId.length = -1;
-        UA_ByteString_newMembers(&request.userIdentityToken.body, 4);
-    }
-    
-    size_t offset = 0;
-    UA_ByteString_encodeBinary(&identityToken.policyId,&request.userIdentityToken.body,&offset);
+    request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+    request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
+    request.userIdentityToken.content.decoded.data = &identityToken;
 
     UA_ActivateSessionResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
@@ -326,7 +316,7 @@ static UA_StatusCode EndpointsHandshake(UA_Client *client) {
     UA_Boolean endpointFound = UA_FALSE;
     UA_Boolean tokenFound = UA_FALSE;
     UA_String securityNone = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
-    for(UA_Int32 i = 0; i < response.endpointsSize; i++) {
+    for(size_t i = 0; i < response.endpointsSize; i++) {
         UA_EndpointDescription* endpoint = &response.endpoints[i];
         /* look out for an endpoint without security */
         if(!UA_String_equal(&endpoint->securityPolicyUri, &securityNone))
@@ -334,7 +324,7 @@ static UA_StatusCode EndpointsHandshake(UA_Client *client) {
         endpointFound = UA_TRUE;
         /* endpoint with no security found */
         /* look for a user token policy with an anonymous token */
-        for(UA_Int32 j=0; j<endpoint->userIdentityTokensSize; ++j) {
+        for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
             UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
             if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
                 continue;
@@ -461,7 +451,7 @@ UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection co
     }
 
     client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
-    if(client->endpointUrl.length < 0) {
+    if(client->endpointUrl.data == NULL) {
         retval = UA_STATUSCODE_BADOUTOFMEMORY;
         goto cleanup;
     }

+ 3 - 13
src/client/ua_client_highlevel.c

@@ -154,22 +154,12 @@ UA_StatusCode __UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClas
     item.browseName = browseName;
     item.nodeClass = nodeClass;
     item.typeDefinition.nodeId = typeDefinition;
-    size_t attributes_length = UA_calcSizeBinary(attr, attributeType);
-    item.nodeAttributes.typeId = attributeType->typeId;
-    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
-    retval = UA_ByteString_newMembers(&item.nodeAttributes.body, attributes_length);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-    size_t offset = 0;
-    retval = UA_encodeBinary(attr, attributeType, &item.nodeAttributes.body, &offset);
-    if(retval != UA_STATUSCODE_GOOD) {
-        UA_ByteString_deleteMembers(&item.nodeAttributes.body);
-        return retval;
-    }
+    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+    item.nodeAttributes.content.decoded.type = attributeType;
+    item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into.
     request.nodesToAdd = &item;
     request.nodesToAddSize = 1;
     UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
-    UA_ByteString_deleteMembers(&item.nodeAttributes.body);
     if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
         retval = response.responseHeader.serviceResult;
         UA_AddNodesResponse_deleteMembers(&response);

+ 16 - 57
src/server/ua_nodes.c

@@ -2,29 +2,16 @@
 #include "ua_util.h"
 
 /* UA_Node */
-static void UA_Node_init(UA_Node *p) {
-	UA_NodeId_init(&p->nodeId);
-	UA_NodeClass_init(&p->nodeClass);
-	UA_QualifiedName_init(&p->browseName);
-	UA_LocalizedText_init(&p->displayName);
-	UA_LocalizedText_init(&p->description);
-	UA_UInt32_init(&p->writeMask);
-	UA_UInt32_init(&p->userWriteMask);
-	p->referencesSize = -1;
-	p->references = NULL;
-}
-
 static void UA_Node_deleteMembers(UA_Node *p) {
 	UA_NodeId_deleteMembers(&p->nodeId);
 	UA_QualifiedName_deleteMembers(&p->browseName);
 	UA_LocalizedText_deleteMembers(&p->displayName);
 	UA_LocalizedText_deleteMembers(&p->description);
-	UA_Array_delete(p->references, &UA_TYPES[UA_TYPES_REFERENCENODE], p->referencesSize);
+	UA_Array_delete(p->references, p->referencesSize, &UA_TYPES[UA_TYPES_REFERENCENODE]);
 }
 
 static UA_StatusCode UA_Node_copy(const UA_Node *src, UA_Node *dst) {
 	UA_StatusCode retval = UA_STATUSCODE_GOOD;
-	UA_Node_init(dst);
 	retval |= UA_NodeId_copy(&src->nodeId, &dst->nodeId);
 	dst->nodeClass = src->nodeClass;
 	retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName);
@@ -32,11 +19,14 @@ static UA_StatusCode UA_Node_copy(const UA_Node *src, UA_Node *dst) {
 	retval |= UA_LocalizedText_copy(&src->description, &dst->description);
 	dst->writeMask = src->writeMask;
 	dst->userWriteMask = src->userWriteMask;
-	dst->referencesSize = src->referencesSize;
-	retval |= UA_Array_copy(src->references, (void**)&dst->references, &UA_TYPES[UA_TYPES_REFERENCENODE],
-                            src->referencesSize);
-	if(retval)
+	if(retval) {
     	UA_Node_deleteMembers(dst);
+        return retval;
+    }
+	retval |= UA_Array_copy(src->references, src->referencesSize, (void**)&dst->references,
+                            &UA_TYPES[UA_TYPES_REFERENCENODE]);
+	if(retval == UA_STATUSCODE_GOOD)
+        dst->referencesSize = src->referencesSize;
 	return retval;
 }
 
@@ -138,10 +128,8 @@ UA_Node * UA_Node_copyAnyNodeClass(const UA_Node *node) {
 
 /* UA_ObjectNode */
 void UA_ObjectNode_init(UA_ObjectNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_ObjectNode));
     p->nodeClass = UA_NODECLASS_OBJECT;
-    p->eventNotifier = 0;
-    p->instanceHandle = NULL;
 }
 
 UA_ObjectNode * UA_ObjectNode_new(void) {
@@ -168,11 +156,8 @@ UA_StatusCode UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
 
 /* UA_ObjectTypeNode */
 void UA_ObjectTypeNode_init(UA_ObjectTypeNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_ObjectTypeNode));
     p->nodeClass = UA_NODECLASS_OBJECTTYPE;
-    p->isAbstract = UA_FALSE;
-    p->lifecycleManagement = (UA_ObjectLifecycleManagement)
-        {.constructor = NULL, .destructor = NULL};
 }
 
 UA_ObjectTypeNode * UA_ObjectTypeNode_new(void) {
@@ -199,16 +184,8 @@ UA_StatusCode UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectType
 
 /* UA_VariableNode */
 void UA_VariableNode_init(UA_VariableNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_VariableNode));
     p->nodeClass = UA_NODECLASS_VARIABLE;
-    p->valueSource = UA_VALUESOURCE_VARIANT;
-    UA_Variant_init(&p->value.variant.value);
-    p->value.variant.callback = (UA_ValueCallback){NULL,NULL,NULL};
-    p->valueRank = -2; // scalar or array of any dimension
-    p->accessLevel = 0;
-    p->userAccessLevel = 0;
-    p->minimumSamplingInterval = 0.0;
-    p->historizing = UA_FALSE;
 }
 
 UA_VariableNode * UA_VariableNode_new(void) {
@@ -230,7 +207,6 @@ void UA_VariableNode_delete(UA_VariableNode *p) {
 }
 
 UA_StatusCode UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
-    UA_VariableNode_init(dst);
 	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
     dst->valueRank = src->valueRank;
     dst->valueSource = src->valueSource;
@@ -252,13 +228,9 @@ UA_StatusCode UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *
 
 /* UA_VariableTypeNode */
 void UA_VariableTypeNode_init(UA_VariableTypeNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_VariableTypeNode));
     p->nodeClass = UA_NODECLASS_VARIABLETYPE;
-    p->valueSource = UA_VALUESOURCE_VARIANT;
-    UA_Variant_init(&p->value.variant.value);
-    p->value.variant.callback = (UA_ValueCallback){NULL, NULL, NULL};
     p->valueRank = -2; // scalar or array of any dimension
-    p->isAbstract = UA_FALSE;
 }
 
 UA_VariableTypeNode * UA_VariableTypeNode_new(void) {
@@ -280,7 +252,6 @@ void UA_VariableTypeNode_delete(UA_VariableTypeNode *p) {
 }
 
 UA_StatusCode UA_VariableTypeNode_copy(const UA_VariableTypeNode *src, UA_VariableTypeNode *dst) {
-    UA_VariableTypeNode_init(dst);
 	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
     dst->valueRank = src->valueRank;
     dst->valueSource = src->valueSource;
@@ -299,11 +270,8 @@ UA_StatusCode UA_VariableTypeNode_copy(const UA_VariableTypeNode *src, UA_Variab
 
 /* UA_ReferenceTypeNode */
 void UA_ReferenceTypeNode_init(UA_ReferenceTypeNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_ReferenceTypeNode));
     p->nodeClass = UA_NODECLASS_REFERENCETYPE;
-    p->isAbstract = UA_FALSE;
-    p->symmetric = UA_FALSE;
-    UA_LocalizedText_init(&p->inverseName);
 }
 
 UA_ReferenceTypeNode * UA_ReferenceTypeNode_new(void) {
@@ -339,14 +307,8 @@ UA_StatusCode UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src, UA_Refe
 
 /* UA_MethodNode */
 void UA_MethodNode_init(UA_MethodNode *p) {
-    UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_MethodNode));
     p->nodeClass = UA_NODECLASS_METHOD;
-    p->executable = UA_FALSE;
-    p->userExecutable = UA_FALSE;
-#ifdef ENABLE_METHODCALLS
-    p->methodHandle        = NULL;
-    p->attachedMethod      = NULL;
-#endif
 }
 
 UA_MethodNode * UA_MethodNode_new(void) {
@@ -387,10 +349,8 @@ UA_StatusCode UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
 
 /* UA_ViewNode */
 void UA_ViewNode_init(UA_ViewNode *p) {
-    UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_ViewNode));
     p->nodeClass = UA_NODECLASS_VIEW;
-    p->containsNoLoops = UA_FALSE;
-    p->eventNotifier = 0;
 }
 
 UA_ViewNode * UA_ViewNode_new(void) {
@@ -417,9 +377,8 @@ UA_StatusCode UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
 
 /* UA_DataTypeNode */
 void UA_DataTypeNode_init(UA_DataTypeNode *p) {
-	UA_Node_init((UA_Node*)p);
+    memset(p, 0, sizeof(UA_DataTypeNode));
     p->nodeClass = UA_NODECLASS_DATATYPE;
-    p->isAbstract = UA_FALSE;
 }
 
 UA_DataTypeNode * UA_DataTypeNode_new(void) {

+ 1 - 1
src/server/ua_nodes.h

@@ -20,7 +20,7 @@
     UA_LocalizedText description;               \
     UA_UInt32 writeMask;                        \
     UA_UInt32 userWriteMask;                    \
-    UA_Int32 referencesSize;                    \
+    size_t referencesSize;                      \
     UA_ReferenceNode *references;
 
 typedef struct {

+ 1 - 1
src/server/ua_nodestore.h

@@ -1,7 +1,7 @@
 #ifndef UA_NODESTORE_H_
 #define UA_NODESTORE_H_
 
-#include "ua_types_generated.h"
+#include "ua_types.h"
 #include "ua_nodes.h"
 
 /**

+ 19 - 22
src/server/ua_server.c

@@ -128,7 +128,7 @@ UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
     if(!parent)
         return UA_STATUSCODE_BADNODEIDINVALID;
     
-    for(int i=0; i<parent->referencesSize; i++) {
+    for(size_t i = 0; i < parent->referencesSize; i++) {
         UA_ReferenceNode *ref = &parent->references[i];
         retval |= callback(ref->targetId.nodeId, ref->isInverse,
                            ref->referenceTypeId, handle);
@@ -179,17 +179,19 @@ __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
     result.statusCode |= UA_NodeId_copy(&requestedNewNodeId,
                                         &item.requestedNewNodeId.nodeId);
     result.statusCode |= UA_NodeId_copy(&typeDefinition, &item.typeDefinition.nodeId);
-    UA_NodeAttributes *attrCopy = UA_alloca(attributeType->memSize);
-    result.statusCode |= UA_copy(attr, attrCopy, attributeType);
+    UA_NodeAttributes *attrCopy;
+    result.statusCode |= UA_Array_copy(attr, 1, (void**)&attrCopy, attributeType);
+    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED;
+    item.nodeAttributes.content.decoded.type = attributeType;
+    item.nodeAttributes.content.decoded.data = attrCopy;
     if(result.statusCode == UA_STATUSCODE_GOOD)
-        Service_AddNodes_single(server, &adminSession, &item, attrCopy, &result);
+        Service_AddNodes_single(server, &adminSession, &item, &result);
 
     if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
         *outNewNodeId = result.addedNodeId;
     else
         UA_AddNodesResult_deleteMembers(&result);
     UA_AddNodesItem_deleteMembers(&item);
-    UA_deleteMembers(attrCopy, attributeType);
     return result.statusCode;
 }
 
@@ -208,11 +210,8 @@ void UA_Server_addNetworkLayer(UA_Server *server, UA_ServerNetworkLayer *network
     server->networkLayers[server->networkLayersSize] = networkLayer;
     server->networkLayersSize++;
 
-    if(server->description.discoveryUrlsSize < 0)
-        server->description.discoveryUrlsSize = 0;
-    UA_String* newUrls;
-    newUrls = UA_realloc(server->description.discoveryUrls,
-                         sizeof(UA_String)*(server->description.discoveryUrlsSize+1));
+    UA_String* newUrls = UA_realloc(server->description.discoveryUrls,
+                                    sizeof(UA_String)*(server->description.discoveryUrlsSize+1));
     if(!newUrls) {
         UA_LOG_ERROR(server->logger, UA_LOGCATEGORY_SERVER, "Adding discoveryUrl");
         return;
@@ -221,7 +220,7 @@ void UA_Server_addNetworkLayer(UA_Server *server, UA_ServerNetworkLayer *network
     UA_String_copy(&networkLayer->discoveryUrl,
                    &server->description.discoveryUrls[server->description.discoveryUrlsSize]);
     server->description.discoveryUrlsSize++;
-    for(UA_Int32 i = 0; i < server->endpointDescriptionsSize; i++) {
+    for(size_t i = 0; i < server->endpointDescriptionsSize; i++) {
         if(!server->endpointDescriptions[i].endpointUrl.data)
             UA_String_copy(&networkLayer->discoveryUrl,
                            &server->endpointDescriptions[i].endpointUrl);
@@ -229,7 +228,7 @@ void UA_Server_addNetworkLayer(UA_Server *server, UA_ServerNetworkLayer *network
 }
 
 void UA_Server_setServerCertificate(UA_Server *server, UA_ByteString certificate) {
-    for(UA_Int32 i = 0; i < server->endpointDescriptionsSize; i++)
+    for(size_t i = 0; i < server->endpointDescriptionsSize; i++)
         UA_ByteString_copy(&certificate,
                            &server->endpointDescriptions[i].serverCertificate);
 }
@@ -256,11 +255,9 @@ void UA_Server_delete(UA_Server *server) {
     UA_Server_deleteExternalNamespaces(server);
 #endif
     UA_ByteString_deleteMembers(&server->serverCertificate);
-    UA_Array_delete(server->namespaces, &UA_TYPES[UA_TYPES_STRING],
-                    server->namespacesSize);
-    UA_Array_delete(server->endpointDescriptions,
-                    &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION],
-                    server->endpointDescriptionsSize);
+    UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
+    UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize,
+                    &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
 
     // Delete the network layers
     for(size_t i = 0; i < server->networkLayersSize; i++) {
@@ -471,7 +468,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
 #endif
 
     /* ns0 and ns1 */
-    server->namespaces = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], 2);
+    server->namespaces = UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
     server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
     UA_String_copy(&server->description.applicationUri, &server->namespaces[1]);
     server->namespacesSize = 2;
@@ -495,7 +492,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
             size++;
         }
         endpoint->userIdentityTokensSize = size;
-        endpoint->userIdentityTokens = UA_Array_new(&UA_TYPES[UA_TYPES_USERTOKENPOLICY], size);
+        endpoint->userIdentityTokens = UA_Array_new(size, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
 
         int currentIndex = 0;
         if(server->config.Login_enableAnonymous){
@@ -949,7 +946,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     UA_VariableNode *serverArray = UA_VariableNode_new();
     copyNames((UA_Node*)serverArray, "ServerArray");
     serverArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERARRAY;
-    serverArray->value.variant.value.data = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], 1);
+    serverArray->value.variant.value.data = UA_Array_new(1, &UA_TYPES[UA_TYPES_STRING]);
     serverArray->value.variant.value.arrayLength = 1;
     serverArray->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     *(UA_String *)serverArray->value.variant.value.data =
@@ -972,7 +969,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     UA_VariableNode *localeIdArray = UA_VariableNode_new();
     copyNames((UA_Node*)localeIdArray, "LocaleIdArray");
     localeIdArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY;
-    localeIdArray->value.variant.value.data = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], 1);
+    localeIdArray->value.variant.value.data = UA_Array_new(1, &UA_TYPES[UA_TYPES_STRING]);
     localeIdArray->value.variant.value.arrayLength = 1;
     localeIdArray->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     *(UA_String *)localeIdArray->value.variant.value.data = UA_STRING_ALLOC("en");
@@ -1016,7 +1013,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     copyNames((UA_Node*)serverProfileArray, "ServerProfileArray");
     serverProfileArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY;
     serverProfileArray->value.variant.value.arrayLength = profileArraySize;
-    serverProfileArray->value.variant.value.data = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], profileArraySize);
+    serverProfileArray->value.variant.value.data = UA_Array_new(profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
     serverProfileArray->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     for(UA_UInt16 i=0;i<profileArraySize;i++)
         ((UA_String *)serverProfileArray->value.variant.value.data)[i] = profileArray[i];

+ 1 - 1
src/server/ua_server_binary.c

@@ -466,5 +466,5 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
                         connection->sockfd, pos, targetpos);
             pos = targetpos;
         }
-    } while(msg->length > (UA_Int32)pos);
+    } while(msg->length > pos);
 }

+ 1 - 1
src/server/ua_server_internal.h

@@ -36,7 +36,7 @@ struct UA_Server {
     UA_DateTime startTime;
     UA_DateTime buildDate;
     UA_ApplicationDescription description;
-    UA_Int32 endpointDescriptionsSize;
+    size_t endpointDescriptionsSize;
     UA_EndpointDescription *endpointDescriptions;
 
     /* Communication */

+ 1 - 1
src/server/ua_services.h

@@ -108,7 +108,7 @@ void Service_CloseSession(UA_Server *server, UA_Session *session, const UA_Close
 void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
                       UA_AddNodesResponse *response);
 void Service_AddNodes_single(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
-                             UA_NodeAttributes *attr, UA_AddNodesResult *result);
+                             UA_AddNodesResult *result);
 
 /** Used to add one or more References to one or more Nodes. */
 void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddReferencesRequest *request,

+ 25 - 8
src/server/ua_services_attribute.c

@@ -47,7 +47,7 @@ UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range) {
     size_t dimensionsMax = 0;
     struct UA_NumericRangeDimension *dimensions = NULL;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_Int32 pos = 0;
+    size_t pos = 0;
     do {
         /* alloc dimensions */
         if(index >= (UA_Int32)dimensionsMax) {
@@ -181,14 +181,14 @@ static const UA_String binEncoding = {sizeof("DefaultBinary")-1, (UA_Byte*)"Defa
 /** Reads a single attribute from a node in the nodestore. */
 void Service_Read_single(UA_Server *server, UA_Session *session, const UA_TimestampsToReturn timestamps,
                          const UA_ReadValueId *id, UA_DataValue *v) {
-	if(id->dataEncoding.name.length >= 0 && !UA_String_equal(&binEncoding, &id->dataEncoding.name)) {
+	if(!UA_String_equal(&binEncoding, &id->dataEncoding.name)) {
            v->hasStatus = UA_TRUE;
            v->status = UA_STATUSCODE_BADDATAENCODINGINVALID;
            return;
 	}
 
 	//index range for a non-value
-	if(id->indexRange.length >= 0 && id->attributeId != UA_ATTRIBUTEID_VALUE){
+	if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE){
 		v->hasStatus = UA_TRUE;
 		v->status = UA_STATUSCODE_BADINDEXRANGENODATA;
 		return;
@@ -333,7 +333,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
     }
 
     size_t size = request->nodesToReadSize;
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_DATAVALUE], size);
+    response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_DATAVALUE]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -479,6 +479,22 @@ Service_Write_single_ValueDataSource(UA_Server *server, UA_Session *session, con
     return retval;
 }
 
+enum type_equivalence {
+    TYPE_EQUIVALENCE_NONE,
+    TYPE_EQUIVALENCE_ENUM,
+    TYPE_EQUIVALENCE_OPAQUE
+};
+
+static enum type_equivalence typeEquivalence(const UA_DataType *type) {
+    if(type->membersSize != 1 || !type->members[0].namespaceZero)
+        return TYPE_EQUIVALENCE_NONE;
+    if(type->members[0].memberTypeIndex == UA_TYPES_INT32)
+        return TYPE_EQUIVALENCE_ENUM;
+    if(type->members[0].memberTypeIndex == UA_TYPES_BYTE && type->members[0].isArray)
+        return TYPE_EQUIVALENCE_OPAQUE;
+    return TYPE_EQUIVALENCE_NONE;
+}
+
 /* In the multithreaded case, node is a copy */
 static UA_StatusCode
 MoveValueIntoNode(UA_Server *server, UA_Session *session, UA_VariableNode *node, UA_WriteValue *wvalue) {
@@ -505,8 +521,9 @@ MoveValueIntoNode(UA_Server *server, UA_Session *session, UA_VariableNode *node,
     if(!UA_NodeId_equal(&oldV->type->typeId, &newV->type->typeId)) {
         cast_v = wvalue->value.value;
         newV = &cast_v;
-        if(oldV->type->namespaceZero && newV->type->namespaceZero &&
-           oldV->type->typeIndex == newV->type->typeIndex) {
+        enum type_equivalence te1 = typeEquivalence(oldV->type);
+        enum type_equivalence te2 = typeEquivalence(newV->type);
+        if(te1 != TYPE_EQUIVALENCE_NONE && te1 == te2) {
             /* An enum was sent as an int32, or an opaque type as a bytestring. This is
                detected with the typeIndex indicated the "true" datatype. */
             newV->type = oldV->type;
@@ -678,7 +695,7 @@ void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest
         return;
     }
 
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_STATUSCODE], request->nodesToWriteSize);
+    response->results = UA_Array_new(request->nodesToWriteSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -707,7 +724,7 @@ void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest
 #endif
     
     response->resultsSize = request->nodesToWriteSize;
-    for(UA_Int32 i = 0;i < request->nodesToWriteSize;i++) {
+    for(size_t i = 0;i < request->nodesToWriteSize;i++) {
 #ifdef UA_EXTERNAL_NAMESPACES
         if(!isExternal[i])
 #endif

+ 4 - 4
src/server/ua_services_discovery.c

@@ -24,14 +24,14 @@ void Service_GetEndpoints(UA_Server *server, const UA_GetEndpointsRequest *reque
 	UA_Boolean *relevant_endpoints = UA_alloca(sizeof(UA_Boolean)*server->endpointDescriptionsSize);
 #endif /*NO_ALLOCA */
     size_t relevant_count = 0;
-    for(UA_Int32 j = 0; j < server->endpointDescriptionsSize; j++) {
+    for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
         relevant_endpoints[j] = UA_FALSE;
         if(request->profileUrisSize <= 0) {
             relevant_endpoints[j] = UA_TRUE;
             relevant_count++;
             continue;
         }
-        for(UA_Int32 i = 0; i < request->profileUrisSize; i++) {
+        for(size_t i = 0; i < request->profileUrisSize; i++) {
             if(UA_String_equal(&request->profileUris[i], &server->endpointDescriptions->transportProfileUri)) {
                 relevant_endpoints[j] = UA_TRUE;
                 relevant_count++;
@@ -53,7 +53,7 @@ void Service_GetEndpoints(UA_Server *server, const UA_GetEndpointsRequest *reque
 
     size_t k = 0;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    for(UA_Int32 j = 0; j < server->endpointDescriptionsSize && retval == UA_STATUSCODE_GOOD; j++) {
+    for(size_t j = 0; j < server->endpointDescriptionsSize && retval == UA_STATUSCODE_GOOD; j++) {
         if(relevant_endpoints[j] != UA_TRUE)
             continue;
         retval = UA_EndpointDescription_copy(&server->endpointDescriptions[j], &response->endpoints[k]);
@@ -62,7 +62,7 @@ void Service_GetEndpoints(UA_Server *server, const UA_GetEndpointsRequest *reque
 
     if(retval != UA_STATUSCODE_GOOD) {
         response->responseHeader.serviceResult = retval;
-        UA_Array_delete(response->endpoints, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], --k);
+        UA_Array_delete(response->endpoints, --k, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
         return;
     }
     response->endpointsSize = relevant_count;

+ 62 - 73
src/server/ua_services_nodemanagement.c

@@ -126,17 +126,20 @@ copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *va
     UA_NodeId_copy(referenceType, &item.referenceTypeId);
     UA_QualifiedName_copy(&node->browseName, &item.browseName);
     item.nodeClass = UA_NODECLASS_VARIABLE;
+    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+    item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES];
+    item.nodeAttributes.content.decoded.data = &attr;
     // don't add a typedefinition here.
 
     // add the new variable
     UA_AddNodesResult res;
     UA_AddNodesResult_init(&res);
-    Service_AddNodes_single(server, session, &item, (UA_NodeAttributes*)&attr, &res);
+    Service_AddNodes_single(server, session, &item, &res);
     UA_VariableAttributes_deleteMembers(&attr);
     UA_AddNodesItem_deleteMembers(&item);
 
     // now instantiate the variable for all hastypedefinition references
-    for(UA_Int32 i = 0; i < node->referencesSize; i++) {
+    for(size_t i = 0; i < node->referencesSize; i++) {
         UA_ReferenceNode *rn = &node->references[i];
         if(rn->isInverse)
             continue;
@@ -178,17 +181,20 @@ copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *vari
     UA_NodeId_copy(referenceType, &item.referenceTypeId);
     UA_QualifiedName_copy(&node->browseName, &item.browseName);
     item.nodeClass = UA_NODECLASS_OBJECT;
+    item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+    item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES];
+    item.nodeAttributes.content.decoded.data = &attr;
     // don't add a typedefinition here.
 
     // add the new object
     UA_AddNodesResult res;
     UA_AddNodesResult_init(&res);
-    Service_AddNodes_single(server, session, &item, (UA_NodeAttributes*)&attr, &res);
+    Service_AddNodes_single(server, session, &item, &res);
     UA_ObjectAttributes_deleteMembers(&attr);
     UA_AddNodesItem_deleteMembers(&item);
 
     // now instantiate the object for all hastypedefinition references
-    for(UA_Int32 i = 0; i < node->referencesSize; i++) {
+    for(size_t i = 0; i < node->referencesSize; i++) {
         UA_ReferenceNode *rn = &node->references[i];
         if(rn->isInverse)
             continue;
@@ -237,7 +243,7 @@ instantiateObjectNode(UA_Server *server, UA_Session *session,
     // todo: continuation points if there are too many results
     Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
 
-    for(UA_Int32 i = 0; i < browseResult.referencesSize; i++) {
+    for(size_t i = 0; i < browseResult.referencesSize; i++) {
         UA_ReferenceDescription *rd = &browseResult.references[i];
         if(rd->nodeClass == UA_NODECLASS_METHOD) {
             /* add a reference to the method in the objecttype */
@@ -301,7 +307,7 @@ instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId
     Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
 
     /* add the child properties */
-    for(UA_Int32 i = 0; i < browseResult.referencesSize; i++) {
+    for(size_t i = 0; i < browseResult.referencesSize; i++) {
         UA_ReferenceDescription *rd = &browseResult.references[i];
         copyExistingVariable(server, session, &rd->nodeId.nodeId, &rd->referenceTypeId, nodeId);
     }
@@ -420,30 +426,64 @@ dataTypeNodeFromAttributes(UA_AddNodesItem *item, UA_DataTypeAttributes *attr) {
 }
 
 void Service_AddNodes_single(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
-                             UA_NodeAttributes *attr, UA_AddNodesResult *result) {
+                             UA_AddNodesResult *result) {
+    if(item->nodeAttributes.encoding < UA_EXTENSIONOBJECT_DECODED ||
+       !item->nodeAttributes.content.decoded.type) {
+        result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+        return;
+    }
+    
     /* create the node */
     UA_Node *node;
     switch(item->nodeClass) {
     case UA_NODECLASS_OBJECT:
-        node = objectNodeFromAttributes(item, (UA_ObjectAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = objectNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_VARIABLE:
-        node = variableNodeFromAttributes(item, (UA_VariableAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = variableNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_OBJECTTYPE:
-        node = objectTypeNodeFromAttributes(item, (UA_ObjectTypeAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = objectTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_VARIABLETYPE:
-        node = variableTypeNodeFromAttributes(item, (UA_VariableTypeAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = variableTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_REFERENCETYPE:
-        node = referenceTypeNodeFromAttributes(item, (UA_ReferenceTypeAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = referenceTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_DATATYPE:
-        node = dataTypeNodeFromAttributes(item, (UA_DataTypeAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = dataTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_VIEW:
-        node = viewNodeFromAttributes(item, (UA_ViewAttributes*)attr);
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_VIEWATTRIBUTES]) {
+            result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+            return;
+        }
+        node = viewNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_METHOD:
     case UA_NODECLASS_UNSPECIFIED:
@@ -480,55 +520,6 @@ void Service_AddNodes_single(UA_Server *server, UA_Session *session, UA_AddNodes
         Service_DeleteNodes_single(server, session, &result->addedNodeId, UA_TRUE);
 }
 
-static void Service_AddNodes_single_unparsed(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
-                                             UA_AddNodesResult *result) {
-    /* adding nodes to ns0 is not allowed over the wire */
-    if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
-        result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
-        return;
-    }
-
-    const UA_DataType *attributeType;
-    switch (item->nodeClass) {
-    case UA_NODECLASS_OBJECT:
-        attributeType = &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES];
-        break;
-    case UA_NODECLASS_OBJECTTYPE:
-        attributeType = &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES];
-        break;
-    case UA_NODECLASS_REFERENCETYPE:
-        attributeType = &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES];
-        break;
-    case UA_NODECLASS_VARIABLE:
-        attributeType = &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES];
-        break;
-    case UA_NODECLASS_VIEW:
-        attributeType = &UA_TYPES[UA_TYPES_VIEWATTRIBUTES];
-        break;
-    case UA_NODECLASS_DATATYPE:
-        attributeType = &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES];
-        break;
-    default:
-        result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
-        return;
-    }
-
-    if(!UA_NodeId_equal(&item->nodeAttributes.typeId, &attributeType->typeId)) {
-        result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
-        return;
-    }
-
-    UA_NodeAttributes *attr = UA_alloca(attributeType->memSize);
-    UA_init(attr, attributeType);
-    size_t pos = 0;
-    result->statusCode = UA_decodeBinary(&item->nodeAttributes.body, &pos, attr, attributeType);
-    if(result->statusCode != UA_STATUSCODE_GOOD)
-        return;
-
-    Service_AddNodes_single(server, session, item, attr, result);
-    UA_deleteMembers(attr, attributeType);
-}
-
 void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
                       UA_AddNodesResponse *response) {
     if(request->nodesToAddSize <= 0) {
@@ -537,7 +528,7 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
     }
     size_t size = request->nodesToAddSize;
 
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_ADDNODESRESULT], size);
+    response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -571,11 +562,11 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
 #endif
     
     response->resultsSize = size;
-    for(size_t i = 0;i < size;i++) {
+    for(size_t i = 0; i < size; i++) {
 #ifdef UA_EXTERNAL_NAMESPACES
         if(!isExternal[i])
 #endif
-            Service_AddNodes_single_unparsed(server, session, &request->nodesToAdd[i], &response->results[i]);
+            Service_AddNodes_single(server, session, &request->nodesToAdd[i], &response->results[i]);
     }
 }
 
@@ -741,8 +732,6 @@ UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
 static UA_StatusCode
 addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, const UA_AddReferencesItem *item) {
 	size_t i = node->referencesSize;
-	if(node->referencesSize < 0)
-		i = 0;
     size_t refssize = (i+1) | 3; // so the realloc is not necessary every time
 	UA_ReferenceNode *new_refs = UA_realloc(node->references, sizeof(UA_ReferenceNode) * refssize);
 	if(!new_refs)
@@ -825,7 +814,7 @@ void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddR
 #endif
 
 	response->resultsSize = size;
-	for(UA_Int32 i = 0; i < response->resultsSize; i++) {
+	for(size_t i = 0; i < response->resultsSize; i++) {
 #ifdef UA_EXTERNAL_NAMESPACES
 		if(!isExternal[i])
 #endif
@@ -849,7 +838,7 @@ UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
         UA_DeleteReferencesItem_init(&delItem);
         delItem.deleteBidirectional = UA_FALSE;
         delItem.targetNodeId.nodeId = *nodeId;
-        for(int i = 0; i < node->referencesSize; i++) {
+        for(size_t i = 0; i < node->referencesSize; i++) {
             delItem.sourceNodeId = node->references[i].targetId.nodeId;
             delItem.isForward = node->references[i].isInverse;
             Service_DeleteReferences_single(server, session, &delItem);
@@ -871,7 +860,7 @@ UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
         UA_BrowseResult result;
         UA_BrowseResult_init(&result);
         Service_Browse_single(server, &adminSession, NULL, &bd, UA_UINT32_MAX, &result);
-        for(int i = 0; i < result.referencesSize; i++) {
+        for(size_t i = 0; i < result.referencesSize; i++) {
             /* call the destructor */
             UA_ReferenceDescription *rd = &result.references[i];
             const UA_ObjectTypeNode *type = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, &rd->nodeId.nodeId);
@@ -904,7 +893,7 @@ void Service_DeleteNodes(UA_Server *server, UA_Session *session, const UA_Delete
         return;
     }
     response->resultsSize = request->nodesToDeleteSize;
-    for(int i=0; i<request->nodesToDeleteSize; i++) {
+    for(size_t i=0; i<request->nodesToDeleteSize; i++) {
         UA_DeleteNodesItem *item = &request->nodesToDelete[i];
         response->results[i] = Service_DeleteNodes_single(server, session, &item->nodeId,
                                                           item->deleteTargetReferences);
@@ -968,7 +957,7 @@ void Service_DeleteReferences(UA_Server *server, UA_Session *session,
         return;
     }
     response->resultsSize = request->referencesToDeleteSize;
-    for(int i=0; i<request->referencesToDeleteSize; i++)
+    for(size_t i = 0; i < request->referencesToDeleteSize; i++)
         response->results[i] = Service_DeleteReferences_single(server, session,
                                                                &request->referencesToDelete[i]);
 }

+ 20 - 16
src/server/ua_services_session.c

@@ -7,8 +7,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
                            const UA_CreateSessionRequest *request,
                            UA_CreateSessionResponse *response) {
     response->responseHeader.serviceResult =
-        UA_Array_copy(server->endpointDescriptions, (void**)&response->serverEndpoints,
-                      &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], server->endpointDescriptionsSize);
+        UA_Array_copy(server->endpointDescriptions, server->endpointDescriptionsSize,
+                      (void**)&response->serverEndpoints, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
         return;
     response->serverEndpointsSize = server->endpointDescriptionsSize;
@@ -68,13 +68,17 @@ void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
                  channel->securityToken.channelId, foundSession->sessionId.namespaceIndex,
                  foundSession->sessionId.identifier.numeric);
 
-    UA_UserIdentityToken token;
-    UA_UserIdentityToken_init(&token);
-    size_t offset = 0;
-    UA_UserIdentityToken_decodeBinary(&request->userIdentityToken.body, &offset, &token);
-
-    UA_UserNameIdentityToken username_token;
-    UA_UserNameIdentityToken_init(&username_token);
+    if(request->userIdentityToken.encoding < UA_EXTENSIONOBJECT_DECODED ||
+       (request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN] &&
+        request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN])) {
+        UA_LOG_DEBUG(server->logger, UA_LOGCATEGORY_SESSION,
+                     "Invalided UserIdentityToken on SecureChannel %i for Session (ns=%i,i=%i)",
+                     channel->securityToken.channelId, foundSession->sessionId.namespaceIndex,
+                     foundSession->sessionId.identifier.numeric);
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+        return;
+    }
+    const UA_UserIdentityToken token = *(const UA_UserIdentityToken*)request->userIdentityToken.content.decoded.data;
 
     UA_String ap = UA_STRING(ANONYMOUS_POLICY);
     UA_String up = UA_STRING(USERNAME_POLICY);
@@ -93,19 +97,21 @@ void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
         UA_SecureChannel_attachSession(channel, foundSession);
         foundSession->activated = UA_TRUE;
         UA_Session_updateLifetime(foundSession);
-    } else if(server->config.Login_enableUsernamePassword && UA_String_equal(&token.policyId, &up)) {
+    } else if(server->config.Login_enableUsernamePassword && UA_String_equal(&token.policyId, &up) &&
+              request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
         /* 3) username logins */
-        offset = 0;
-        UA_UserNameIdentityToken_decodeBinary(&request->userIdentityToken.body, &offset, &username_token);
+        const UA_UserNameIdentityToken username_token =
+            *(const UA_UserNameIdentityToken*)request->userIdentityToken.content.decoded.data;
+
         if(username_token.encryptionAlgorithm.data != NULL) {
             /* 3.1) we only support encryption */
             response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
-        } else  if(username_token.userName.length == -1 && username_token.password.length == -1){
+        } else  if(username_token.userName.data == NULL && username_token.password.data == NULL){
             /* 3.2) empty username and password */
             response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
         } else {
             /* 3.3) ok, trying to match the username */
-            UA_UInt32 i = 0;
+            size_t i = 0;
             for(; i < server->config.Login_loginsCount; ++i) {
                 UA_String user = UA_STRING(server->config.Login_usernames[i]);
                 UA_String pw = UA_STRING(server->config.Login_passwords[i]);
@@ -127,8 +133,6 @@ void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
     } else {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
     }
-    UA_UserIdentityToken_deleteMembers(&token);
-    UA_UserNameIdentityToken_deleteMembers(&username_token);
     return;
 }
 

+ 20 - 23
src/server/ua_services_view.c

@@ -24,7 +24,7 @@ fillReferenceDescription(UA_NodeStore *ns, const UA_Node *curr, UA_ReferenceNode
         retval |= UA_LocalizedText_copy(&curr->displayName, &descr->displayName);
     if(mask & UA_BROWSERESULTMASK_TYPEDEFINITION){
         if(curr->nodeClass == UA_NODECLASS_OBJECT || curr->nodeClass == UA_NODECLASS_VARIABLE) {
-            for(UA_Int32 i = 0; i < curr->referencesSize; i++) {
+            for(size_t i = 0; i < curr->referencesSize; i++) {
                 UA_ReferenceNode *refnode = &curr->references[i];
                 if(refnode->referenceTypeId.identifier.numeric != UA_NS0ID_HASTYPEDEFINITION)
                     continue;
@@ -169,7 +169,7 @@ findSubTypes(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size
         node = UA_NodeStore_get(ns, &results[index]);
         if(!node || node->nodeClass != UA_NODECLASS_REFERENCETYPE)
             continue;
-        for(UA_Int32 i = 0; i < node->referencesSize; i++) {
+        for(size_t i = 0; i < node->referencesSize; i++) {
             if(node->references[i].referenceTypeId.identifier.numeric != UA_NS0ID_HASSUBTYPE ||
                node->references[i].isInverse == UA_TRUE)
                 continue;
@@ -194,7 +194,7 @@ findSubTypes(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size
     } while(++index <= last && retval == UA_STATUSCODE_GOOD);
 
     if(retval) {
-        UA_Array_delete(results, &UA_TYPES[UA_TYPES_NODEID], last);
+        UA_Array_delete(results, last, &UA_TYPES[UA_TYPES_NODEID]);
         return retval;
     }
 
@@ -226,7 +226,7 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
                       const UA_BrowseDescription *descr, UA_UInt32 maxrefs, UA_BrowseResult *result) {
     UA_UInt32 continuationIndex = 0;
     size_t referencesCount = 0;
-    UA_Int32 referencesIndex = 0;
+    size_t referencesIndex = 0;
     
     /* set the browsedescription if a cp is given */
     if(cp) {
@@ -275,7 +275,7 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
     if(!node) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         if(!all_refs && descr->includeSubtypes)
-            UA_Array_delete(relevant_refs, &UA_TYPES[UA_TYPES_NODEID], relevant_refs_size);
+            UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
         return;
     }
 
@@ -284,7 +284,7 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
         result->referencesSize = 0;
         UA_NodeStore_release(node);
         if(!all_refs && descr->includeSubtypes)
-            UA_Array_delete(relevant_refs, &UA_TYPES[UA_TYPES_NODEID], relevant_refs_size);
+            UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
         return;
     }
 
@@ -338,7 +338,7 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
         UA_NodeStore_release(current);
 #endif
         if(retval != UA_STATUSCODE_GOOD) {
-            UA_Array_delete(result->references, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], referencesCount);
+            UA_Array_delete(result->references, referencesCount, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
             result->references = NULL;
             result->referencesSize = 0;
             result->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
@@ -356,7 +356,7 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
     cleanup:
     UA_NodeStore_release(node);
     if(!all_refs && descr->includeSubtypes)
-        UA_Array_delete(relevant_refs, &UA_TYPES[UA_TYPES_NODEID], relevant_refs_size);
+        UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
     if(result->statusCode != UA_STATUSCODE_GOOD)
         return;
 
@@ -409,7 +409,7 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
     }
 
     size_t size = request->nodesToBrowseSize;
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_BROWSERESULT], size);
+    response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -463,7 +463,7 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseN
    size_t size = request->continuationPointsSize;
    if(!request->releaseContinuationPoints) {
        /* continue with the cp */
-       response->results = UA_Array_new(&UA_TYPES[UA_TYPES_BROWSERESULT], size);
+       response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
        if(!response->results) {
            response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
            return;
@@ -482,7 +482,7 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseN
        }
    } else {
        /* remove the cp */
-       response->results = UA_Array_new(&UA_TYPES[UA_TYPES_BROWSERESULT], size);
+       response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
        if(!response->results) {
            response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
            return;
@@ -508,12 +508,9 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseN
 
 static UA_StatusCode
 walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *node, const UA_RelativePath *path,
-               UA_Int32 pathindex, UA_BrowsePathTarget **targets, UA_Int32 *targets_size,
-               UA_Int32 *target_count) {
+               size_t pathindex, UA_BrowsePathTarget **targets, size_t *targets_size,
+               size_t *target_count) {
     const UA_RelativePathElement *elem = &path->elements[pathindex];
-    if(elem->targetName.name.length == -1)
-        return UA_STATUSCODE_BADBROWSENAMEINVALID;
-
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_NodeId *reftypes = NULL;
     size_t reftypes_count = 1; // all_refs or no subtypes => 1
@@ -528,7 +525,7 @@ walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *node, cons
             return retval;
     }
 
-    for(UA_Int32 i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
+    for(size_t i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
         UA_Boolean match = all_refs;
         for(size_t j = 0; j < reftypes_count && !match; j++) {
             if(node->references[i].isInverse == elem->isInverse &&
@@ -581,7 +578,7 @@ walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *node, cons
     }
 
     if(!all_refs && elem->includeSubtypes)
-        UA_Array_delete(reftypes, &UA_TYPES[UA_TYPES_NODEID], (UA_Int32)reftypes_count);
+        UA_Array_delete(reftypes, reftypes_count, &UA_TYPES[UA_TYPES_NODEID]);
     return retval;
 }
 
@@ -592,7 +589,7 @@ void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session
         return;
     }
         
-    UA_Int32 arraySize = 10;
+    size_t arraySize = 10;
     result->targets = UA_malloc(sizeof(UA_BrowsePathTarget) * arraySize);
     if(!result->targets) {
         result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
@@ -612,7 +609,7 @@ void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session
     if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD)
         result->statusCode = UA_STATUSCODE_BADNOMATCH;
     if(result->statusCode != UA_STATUSCODE_GOOD) {
-        UA_Array_delete(result->targets, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], result->targetsSize);
+        UA_Array_delete(result->targets, result->targetsSize, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET]);
         result->targets = NULL;
         result->targetsSize = -1;
     }
@@ -630,7 +627,7 @@ void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *sessio
     }
 
     size_t size = request->browsePathsSize;
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_BROWSEPATHRESULT], size);
+    response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -684,8 +681,8 @@ void Service_RegisterNodes(UA_Server *server, UA_Session *session, const UA_Regi
         response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
     else {
         response->responseHeader.serviceResult =
-            UA_Array_copy(request->nodesToRegister, (void**)&response->registeredNodeIds,
-                          &UA_TYPES[UA_TYPES_NODEID], request->nodesToRegisterSize);
+            UA_Array_copy(request->nodesToRegister, request->nodesToRegisterSize,
+                          (void**)&response->registeredNodeIds, &UA_TYPES[UA_TYPES_NODEID]);
         if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
             response->registeredNodeIdsSize = request->nodesToRegisterSize;
     }

+ 3 - 7
src/ua_connection.c

@@ -30,9 +30,6 @@ void UA_Connection_deleteMembers(UA_Connection *connection) {
 
 UA_Job UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString received) {
     UA_Job job = (UA_Job){.type = UA_JOBTYPE_NOTHING};
-    if(received.length == -1)
-        return job;
-
     UA_ByteString current;
     if(connection->incompleteMessage.length <= 0)
         current = received;
@@ -69,13 +66,12 @@ UA_Job UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString r
         UA_Int32 length = 0;
         size_t length_pos = pos + 4;
         UA_StatusCode retval = UA_Int32_decodeBinary(&current, &length_pos, &length);
-        if(retval != UA_STATUSCODE_GOOD || length < 16 ||
-           length > (UA_Int32)connection->localConf.maxMessageSize) {
+        if(retval != UA_STATUSCODE_GOOD || length < 16 || length > (UA_Int32)connection->localConf.maxMessageSize) {
             /* the message size is not allowed. throw the remaining bytestring away */
             current.length = pos;
             break;
         }
-        if(length + (UA_Int32)pos > current.length)
+        if(length + pos > current.length)
             break; /* the message is incomplete. keep the beginning */
         pos += length;
     }
@@ -102,7 +98,7 @@ UA_Job UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString r
         return job;
     }
 
-    if(current.length != (UA_Int32)pos) {
+    if(current.length != pos) {
         /* there is an incomplete message at the end of current */
         connection->incompleteMessage.data = UA_malloc(current.length - pos);
         if(connection->incompleteMessage.data) {

+ 1 - 1
src/ua_securechannel.h

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

ファイルの差分が大きいため隠しています
+ 348 - 550
src/ua_types.c


ファイルの差分が大きいため隠しています
+ 447 - 611
src/ua_types_encoding_binary.c


+ 130 - 48
src/ua_types_encoding_binary.h

@@ -28,56 +28,138 @@
  * @{
  */
 
-#define UA_TYPE_BINARY_ENCODING(TYPE)                                   \
-    UA_StatusCode TYPE##_encodeBinary(TYPE const *src, UA_ByteString *dst, size_t *UA_RESTRICT offset); \
-    UA_StatusCode TYPE##_decodeBinary(UA_ByteString const *src, size_t *UA_RESTRICT offset, TYPE *dst);
-
-UA_TYPE_BINARY_ENCODING(UA_Boolean)
-UA_TYPE_BINARY_ENCODING(UA_Byte)
-#define UA_SByte_encodeBinary(src, dst, offset) UA_Byte_encodeBinary((const UA_Byte *)src, dst, offset)
-#define UA_SByte_decodeBinary(src, offset, dst) UA_Byte_decodeBinary(src, offset, (UA_Byte *)dst)
-UA_TYPE_BINARY_ENCODING(UA_UInt16)
-#define UA_Int16_encodeBinary(src, dst, offset) UA_UInt16_encodeBinary((const UA_UInt16 *)src, dst, offset)
-#define UA_Int16_decodeBinary(src, offset, dst) UA_UInt16_decodeBinary(src, offset, (UA_UInt16 *)dst)
-UA_TYPE_BINARY_ENCODING(UA_UInt32)
-#define UA_Int32_encodeBinary(src, dst, offset) UA_UInt32_encodeBinary((const UA_UInt32 *)src, dst, offset)
-#define UA_Int32_decodeBinary(src, offset, dst) UA_UInt32_decodeBinary(src, offset, (UA_UInt32 *)dst)
-UA_TYPE_BINARY_ENCODING(UA_UInt64)
-#define UA_Int64_encodeBinary(src, dst, offset) UA_UInt64_encodeBinary((const UA_UInt64 *)src, dst, offset)
-#define UA_Int64_decodeBinary(src, offset, dst) UA_UInt64_decodeBinary(src, offset, (UA_UInt64 *)dst)
-#ifdef UA_MIXED_ENDIAN
- UA_TYPE_BINARY_ENCODING(UA_Float)
- UA_TYPE_BINARY_ENCODING(UA_Double)
-#else
- #define UA_Float_encodeBinary(src, dst, offset) UA_UInt32_encodeBinary((const UA_UInt32 *)src, dst, offset)
- #define UA_Float_decodeBinary(src, offset, dst) UA_UInt32_decodeBinary(src, offset, (UA_UInt32 *)dst)
- #define UA_Double_encodeBinary(src, dst, offset) UA_UInt64_encodeBinary((const UA_UInt64 *)src, dst, offset)
- #define UA_Double_decodeBinary(src, offset, dst) UA_UInt64_decodeBinary(src, offset, (UA_UInt64 *)dst)
-#endif
-UA_TYPE_BINARY_ENCODING(UA_String)
-#define UA_DateTime_encodeBinary(src, dst, offset) UA_UInt64_encodeBinary((const UA_UInt64 *)src, dst, offset)
-#define UA_DateTime_decodeBinary(src, offset, dst) UA_UInt64_decodeBinary(src, offset, (UA_UInt64 *)dst)
-UA_TYPE_BINARY_ENCODING(UA_Guid)
-#define UA_ByteString_encodeBinary(src, dst, offset) UA_String_encodeBinary((const UA_String *)src, dst, offset)
-#define UA_ByteString_decodeBinary(src, offset, dst) UA_String_decodeBinary(src, offset, (UA_String *)dst)
-#define UA_XmlElement_encodeBinary(src, dst, offset) UA_String_encodeBinary((const UA_String *)src, dst, offset)
-#define UA_XmlElement_decodeBinary(src, offset, dst) UA_String_decodeBinary(src, offset, (UA_String *)dst)
-UA_TYPE_BINARY_ENCODING(UA_NodeId)
-UA_TYPE_BINARY_ENCODING(UA_ExpandedNodeId)
-#define UA_StatusCode_encodeBinary(src, dst, offset) UA_UInt32_encodeBinary((const UA_UInt32 *)src, dst, offset)
-#define UA_StatusCode_decodeBinary(src, offset, dst) UA_UInt32_decodeBinary(src, offset, (UA_UInt32 *)dst)
-UA_TYPE_BINARY_ENCODING(UA_QualifiedName)
-UA_TYPE_BINARY_ENCODING(UA_LocalizedText)
-UA_TYPE_BINARY_ENCODING(UA_ExtensionObject)
-UA_TYPE_BINARY_ENCODING(UA_DataValue)
-UA_TYPE_BINARY_ENCODING(UA_Variant)
-UA_TYPE_BINARY_ENCODING(UA_DiagnosticInfo)
-
-UA_StatusCode UA_encodeBinary(const void *src, const UA_DataType *dataType, UA_ByteString *dst,
+/* Generic Types */
+UA_StatusCode UA_encodeBinary(const void *src, const UA_DataType *type, UA_ByteString *dst,
                               size_t *UA_RESTRICT offset) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
 UA_StatusCode UA_decodeBinary(const UA_ByteString *src, size_t * UA_RESTRICT offset, void *dst,
-                              const UA_DataType *dataType) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-size_t UA_calcSizeBinary(const void *p, const UA_DataType *dataType) UA_FUNC_ATTR_PURE;
+                              const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* Builtin Types */
+static UA_INLINE UA_StatusCode UA_Boolean_encodeBinary(const UA_Boolean *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BOOLEAN], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Boolean_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Boolean *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode UA_Byte_encodeBinary(const UA_Byte *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTE], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Byte_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Byte *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BYTE]); }
+
+static UA_INLINE UA_StatusCode UA_SByte_encodeBinary(const UA_SByte *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SBYTE], dst, offset); }
+static UA_INLINE UA_StatusCode UA_SByte_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_SByte *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SBYTE]); }
+
+static UA_INLINE UA_StatusCode UA_UInt16_encodeBinary(const UA_UInt16 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT16], dst, offset); }
+static UA_INLINE UA_StatusCode UA_UInt16_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_UInt16 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT16]); }
+
+static UA_INLINE UA_StatusCode UA_Int16_encodeBinary(const UA_Int16 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT16], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Int16_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Int16 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT16]); }
+
+static UA_INLINE UA_StatusCode UA_UInt32_encodeBinary(const UA_UInt32 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT32], dst, offset); }
+static UA_INLINE UA_StatusCode UA_UInt32_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_UInt32 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode UA_Int32_encodeBinary(const UA_Int32 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT32], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Int32_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Int32 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT32]); }
+
+static UA_INLINE UA_StatusCode UA_UInt64_encodeBinary(const UA_UInt64 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT64], dst, offset); }
+static UA_INLINE UA_StatusCode UA_UInt64_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_UInt64 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_UINT64]); }
+
+static UA_INLINE UA_StatusCode UA_Int64_encodeBinary(const UA_Int64 *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT64], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Int64_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Int64 *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_INT64]); }
+
+static UA_INLINE UA_StatusCode UA_Float_encodeBinary(const UA_Float *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FLOAT], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Float_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Float *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FLOAT]); }
+
+static UA_INLINE UA_StatusCode UA_Double_encodeBinary(const UA_Double *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DOUBLE], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Double_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Double *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DOUBLE]); }
+
+static UA_INLINE UA_StatusCode UA_String_encodeBinary(const UA_String*src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRING], dst, offset); }
+static UA_INLINE UA_StatusCode UA_String_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_String *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STRING]); }
+
+static UA_INLINE UA_StatusCode UA_DateTime_encodeBinary(const UA_DateTime *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATETIME], dst, offset); }
+static UA_INLINE UA_StatusCode UA_DateTime_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_DateTime *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATETIME]); }
+
+static UA_INLINE UA_StatusCode UA_Guid_encodeBinary(const UA_Guid *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GUID], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Guid_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Guid *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_GUID]); }
+
+static UA_INLINE UA_StatusCode UA_ByteString_encodeBinary(const UA_ByteString *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTESTRING], dst, offset); }
+static UA_INLINE UA_StatusCode UA_ByteString_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_ByteString *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_BYTESTRING]); }
+
+static UA_INLINE UA_StatusCode UA_XmlElement_encodeBinary(const UA_XmlElement *src, UA_XmlElement *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_XMLELEMENT], dst, offset); }
+static UA_INLINE UA_StatusCode UA_XmlElement_decodeBinary(const UA_XmlElement *src, size_t *UA_RESTRICT offset, UA_XmlElement *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_XMLELEMENT]); }
+
+static UA_INLINE UA_StatusCode UA_NodeId_encodeBinary(const UA_NodeId *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEID], dst, offset); }
+static UA_INLINE UA_StatusCode UA_NodeId_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_NodeId *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODEID]); }
+
+static UA_INLINE UA_StatusCode UA_ExpandedNodeId_encodeBinary(const UA_ExpandedNodeId *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXPANDEDNODEID], dst, offset); }
+static UA_INLINE UA_StatusCode UA_ExpandedNodeId_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_ExpandedNodeId *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); }
+
+static UA_INLINE UA_StatusCode UA_StatusCode_encodeBinary(const UA_StatusCode *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STATUSCODE], dst, offset); }
+static UA_INLINE UA_StatusCode UA_StatusCode_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_StatusCode *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_STATUSCODE]); }
+
+static UA_INLINE UA_StatusCode UA_QualifiedName_encodeBinary(const UA_QualifiedName*src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUALIFIEDNAME], dst, offset); }
+static UA_INLINE UA_StatusCode UA_QualifiedName_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_QualifiedName *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+
+static UA_INLINE UA_StatusCode UA_LocalizedText_encodeBinary(const UA_LocalizedText *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], dst, offset); }
+static UA_INLINE UA_StatusCode UA_LocalizedText_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_LocalizedText *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode UA_ExtensionObject_encodeBinary(const UA_ExtensionObject *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], dst, offset); }
+static UA_INLINE UA_StatusCode UA_ExtensionObject_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_ExtensionObject *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); }
+
+static UA_INLINE UA_StatusCode UA_DataValue_encodeBinary(const UA_DataValue *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATAVALUE], dst, offset); }
+static UA_INLINE UA_StatusCode UA_DataValue_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_DataValue *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DATAVALUE]); }
+
+static UA_INLINE UA_StatusCode UA_Variant_encodeBinary(const UA_Variant *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIANT], dst, offset); }
+static UA_INLINE UA_StatusCode UA_Variant_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_Variant *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_VARIANT]); }
+
+static UA_INLINE UA_StatusCode UA_DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, UA_ByteString *dst, size_t *UA_RESTRICT offset) {
+    return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], dst, offset); }
+static UA_INLINE UA_StatusCode UA_DiagnosticInfo_decodeBinary(const UA_ByteString *src, size_t *UA_RESTRICT offset, UA_DiagnosticInfo *dst) {
+    return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]); }
 
 /// @}
 

+ 29 - 33
tools/generate_datatypes.py

@@ -124,16 +124,16 @@ class BuiltinType(object):
         if self.name in ["UA_String", "UA_ByteString", "UA_XmlElement"]:
             return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
                 ".memSize = sizeof(" + self.name + "), " + \
-                ".namespaceZero = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
+                ".builtin = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
                 ".membersSize = 1,\n\t.members = {{.memberTypeIndex = UA_TYPES_BYTE, .namespaceZero = UA_TRUE, " + \
-                (".memberName = (char*)0, " if typeintrospection else "") + \
-                ".padding = offsetof(UA_String, data) - sizeof(UA_Int32), .isArray = UA_TRUE }}, " + \
+                (".memberName = \"\", " if typeintrospection else "") + \
+                ".padding = offsetof(UA_String, data) - sizeof(size_t), .isArray = UA_TRUE }}, " + \
                 ".typeIndex = %s }" % (outname.upper() + "_" + self.name[3:].upper())
 
         if self.name == "UA_ExpandedNodeId":
             return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
                 ".memSize = sizeof(UA_ExpandedNodeId), " + \
-                ".namespaceZero = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
+                ".builtin = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
                 ".membersSize = 3, .members = {" + \
                 "\n\t{.memberTypeIndex = UA_TYPES_NODEID, .namespaceZero = UA_TRUE, " + \
                 (".memberName = \"nodeId\", " if typeintrospection else "") + \
@@ -149,7 +149,7 @@ class BuiltinType(object):
         if self.name == "UA_QualifiedName":
             return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
                 ".memSize = sizeof(UA_QualifiedName), " + \
-                ".namespaceZero = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
+                ".builtin = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
                 ".membersSize = 2, .members = {" + \
                 "\n\t{.memberTypeIndex = UA_TYPES_UINT16, .namespaceZero = UA_TRUE, " + \
                 (".memberName = \"namespaceIndex\", " if typeintrospection else "") + \
@@ -162,7 +162,7 @@ class BuiltinType(object):
         if self.name == "UA_LocalizedText":
             return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
                 ".memSize = sizeof(UA_LocalizedText), " + \
-                ".namespaceZero = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
+                ".builtin = UA_TRUE, .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
                 ".membersSize = 2, .members = {" + \
                 "\n\t{.memberTypeIndex = UA_TYPES_STRING, .namespaceZero = UA_TRUE, " + \
                 (".memberName = \"locale\", " if typeintrospection else "") + \
@@ -174,10 +174,13 @@ class BuiltinType(object):
 
         return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
             ".memSize = sizeof(" + self.name + "), " + \
-            ".namespaceZero = UA_TRUE, " + \
-            ".fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
+            ".builtin = UA_TRUE, .fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
             ", .zeroCopyable = " + ("UA_TRUE" if self.zero_copy() else "UA_FALSE") + \
-            ", .membersSize = 0, .typeIndex = %s }" % (outname.upper() + "_" + self.name[3:].upper())
+            ", .membersSize = 1, .members = {" + \
+            "\n\t{.memberTypeIndex = UA_TYPES_" + self.name[3:].upper() + " , .namespaceZero = UA_TRUE, " + \
+            (".memberName = \"\", " if typeintrospection else "") + \
+            ".padding = 0, .isArray = UA_FALSE }},\n" + \
+            ".typeIndex = UA_TYPES_" + self.name[3:].upper() + " }"
 
 class EnumerationType(object):
     def __init__(self, name, description = "", elements = OrderedDict()):
@@ -212,19 +215,18 @@ class EnumerationType(object):
         else:
             typeid = "{.namespaceIndex = %s, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = %s}, " % (description.namespaceid, description.nodeid)
         return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
-            ".memSize = sizeof(" + self.name + "), " +\
-            ".namespaceZero = UA_TRUE, " + \
+            ".memSize = sizeof(" + self.name + "), .builtin = UA_FALSE, " + \
             ".fixedSize = UA_TRUE, .zeroCopyable = UA_TRUE, " + \
             ".membersSize = 1,\n\t.members = {{.memberTypeIndex = UA_TYPES_INT32," + \
-            (".memberName = (char*)0, " if typeintrospection else "") + \
-            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }}, .typeIndex = UA_TYPES_INT32 }"
+            (".memberName = \"\", " if typeintrospection else "") + \
+            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }}, .typeIndex = %s }" % (outname.upper() + "_" + self.name[3:].upper())
 
     def functions_c(self, typeTableName):
-        return '''static UA_INLINE %s * %s_new(void) { %s *v = (%s*)UA_Int32_new(); return v; }
-static UA_INLINE void %s_init(%s *p) { UA_Int32_init((UA_Int32*)p); }
-static UA_INLINE void %s_delete(%s *p) { UA_Int32_delete((UA_Int32*)p); }
+        return '''static UA_INLINE %s * %s_new(void) { return UA_new(&UA_TYPES[UA_TYPES_INT32]); }
+static UA_INLINE void %s_init(%s *p) { *p = 0; }
+static UA_INLINE void %s_delete(%s *p) { UA_delete(p, &UA_TYPES[UA_TYPES_INT32]); }
 static UA_INLINE void %s_deleteMembers(%s *p) { }
-static UA_INLINE UA_StatusCode %s_copy(const %s *src, %s *dst) { return UA_Int32_copy((const UA_Int32*)src, (UA_Int32*)dst); }''' % tuple(itertools.repeat(self.name, 13))
+static UA_INLINE UA_StatusCode %s_copy(const %s *src, %s *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }''' % tuple(itertools.repeat(self.name, 11))
 
     def encoding_h(self, typeTableName):
         return '''static UA_INLINE UA_StatusCode %s_encodeBinary(const %s *src, UA_ByteString *dst, size_t *offset) { return UA_Int32_encodeBinary((const UA_Int32*)src, dst, offset); }
@@ -251,16 +253,16 @@ class OpaqueType(object):
             typeid = "{.namespaceIndex = %s, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = %s}, " % (description.namespaceid, description.nodeid)
         return (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
             ".memSize = sizeof(" + self.name + "), .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
-            ".namespaceZero = UA_TRUE, .membersSize = 1,\n\t.members = {{.memberTypeIndex = UA_TYPES_BYTESTRING," + \
-            (".memberName = (char*)0, " if typeintrospection else "") + \
-            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }}, .typeIndex = UA_TYPES_BYTESTRING }"
+            ".builtin = UA_FALSE, .membersSize = 1,\n\t.members = {{.memberTypeIndex = UA_TYPES_BYTE," + \
+            (".memberName = \"\", " if typeintrospection else "") + \
+            ".namespaceZero = UA_TRUE, .padding = offsetof(UA_String, data) - sizeof(size_t), .isArray = UA_TRUE }}, .typeIndex = %s}" % (outname.upper() + "_" + self.name[3:].upper())
 
     def functions_c(self, typeTableName):
         return '''static UA_INLINE %s * %s_new(void) { %s *v = (%s*)UA_ByteString_new(); return v; }
-static UA_INLINE void %s_init(%s *p) { UA_ByteString_init((UA_ByteString*)p); }
+static UA_INLINE void %s_init(%s *p) { memset(p, 0, sizeof(%s); }
 static UA_INLINE void %s_delete(%s *p) { UA_ByteString_delete((UA_ByteString*)p); }
 static UA_INLINE void %s_deleteMembers(%s *p) { }
-static UA_INLINE UA_StatusCode %s_copy(const %s *src, %s *dst) { return UA_ByteString_copy((const UA_ByteString*)src, (UA_ByteString*)dst); }''' % tuple(itertools.repeat(self.name, 13))
+static UA_INLINE UA_StatusCode %s_copy(const %s *src, %s *dst) { return UA_ByteString_copy((const UA_ByteString*)src, (UA_ByteString*)dst); }''' % tuple(itertools.repeat(self.name, 14))
 
     def encoding_h(self, typeTableName):
         return '''static UA_INLINE UA_StatusCode %s_encodeBinary(const %s *src, UA_ByteString *dst, size_t *offset) { return UA_ByteString_encodeBinary((UA_ByteString*)src, dst, offset); }
@@ -309,7 +311,7 @@ class StructType(object):
             values = self.members.items()
         for name, member in values:
             if member.isArray:
-                returnstr += "    UA_Int32 " + name + "Size;\n"
+                returnstr += "    size_t " + name + "Size;\n"
                 returnstr += "    " + member.memberType.name + " *" +name + ";\n"
             else:
                 returnstr += "    " + member.memberType.name + " " +name + ";\n"
@@ -322,7 +324,7 @@ class StructType(object):
             typeid = "{.namespaceIndex = %s, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = %s}, " % (description.namespaceid, description.nodeid)
         layout = (("{.typeName = \"" + self.name[3:] + "\", ") if typeintrospection else "{") + ".typeId = " + typeid + \
                  ".memSize = sizeof(" + self.name + "), "+ \
-                 ".namespaceZero = " + ("UA_TRUE" if namespace_0 else "UA_FALSE") + \
+                 ".builtin = 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") + \
@@ -357,7 +359,7 @@ class StructType(object):
                     length_pos = "offsetof(%s, %sSize)" % (self.name, member.name)
                     if index != 0:
                         layout += "((%s - %s) << 3) + " % (length_pos, before_endpos)
-                    layout += "(%s - sizeof(UA_Int32) - %s)" % (thispos, length_pos)
+                    layout += "(%s - sizeof(size_t) - %s)" % (thispos, length_pos)
                 else:
                     layout += "%s - %s" % (thispos, before_endpos)
                 layout += ", .isArray = " + ("UA_TRUE" if member.isArray else "UA_FALSE") + " }, "
@@ -365,7 +367,7 @@ class StructType(object):
         return layout + "}"
 
     def functions_c(self, typeTableName):
-        return '''static UA_INLINE void %s_init(%s *p) { UA_init(p, %s); }
+        return '''static UA_INLINE void %s_init(%s *p) { memset(p, 0, sizeof(%s)); }
 static UA_INLINE void %s_delete(%s *p) { UA_delete(p, %s); }
 static UA_INLINE void %s_deleteMembers(%s *p) { UA_deleteMembers(p, %s); }
 static UA_INLINE %s * %s_new(void) { return (%s *) UA_new(%s); }
@@ -549,8 +551,7 @@ extern "C" {
 #include "ua_types.h"
 #ifdef UA_INTERNAL
 #include "ua_types_encoding_binary.h"
-#endif'''
- + ('\n#include "ua_types_generated.h"\n' if args.namespace_id != 0 else '') + '''
+#endif
 
 /**
 * @ingroup types
@@ -629,11 +630,6 @@ for t in values:
         printe("/* " + t.name + " */")
         printe(t.encoding_h(outname.upper()))
 printc("};\n")
-# if args.typedescriptions:
-#     printc('const UA_UInt32 *' + outname.upper() + '_IDS = (UA_UInt32[]){')
-#     for t in types.itervalues():
-#         print(str(typedescriptions[t.name].nodeid) + ", ", end='', file=fc)
-#     printc("};")
 
 fh.close()
 fe.close()