Bladeren bron

Simplify variant, arrays, no leaks in check_memory

Array de/encoding now takes a vtable entry instead of an id. This saves many lookups.
The encodingbyte of variants is no longer stored explicitly, but inferred from the other values. => A single source of truth of what is contained in the variant.
Julius Pfrommer 10 jaren geleden
bovenliggende
commit
f0da71bdb2

+ 1 - 2
src/ua_application.c

@@ -47,10 +47,9 @@ void appMockup_init() {
 
 	np = create_node_ns0(UA_VARIABLENODE, UA_NODECLASS_VARIABLE, 2255, "Server_NamespaceArray", "open62541", "..." );
 	UA_VariableNode* v = (UA_VariableNode*)np;
-	UA_Array_new((void**)&v->value.data, 2, UA_STRING);
+	UA_Array_new((void**)&v->value.data, 2, &UA_.types[UA_STRING]);
 	v->value.vt = &UA_.types[UA_STRING];
 	v->value.arrayLength = 2;
-	v->value.encodingMask = UA_VARIANT_ENCODINGMASKTYPE_ARRAY | UA_STRING_NS0;
 	UA_String_copycstring("http://opcfoundation.org/UA/",((UA_String **)(((v)->value).data))[0]);
 	UA_String_copycstring("http://localhost:16664/open62541/",((UA_String **)(((v)->value).data))[1]);
 	v->dataType.encodingByte = UA_NODEIDTYPE_FOURBYTE;

+ 3 - 2
src/ua_services_discovery.c

@@ -3,7 +3,7 @@ UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest*
 	UA_String_printx("endpointUrl=", &request->endpointUrl);
 
 	response->endpointsSize = 1;
-	UA_Array_new((void**) &response->endpoints,response->endpointsSize,UA_ENDPOINTDESCRIPTION);
+	UA_Array_new((void**) &response->endpoints,response->endpointsSize,&UA_.types[UA_ENDPOINTDESCRIPTION]);
 
 	//Security issues:
 	//The policy should be 'http://opcfoundation.org/UA/SecurityPolicy#None'
@@ -14,7 +14,8 @@ UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest*
 	UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary", &response->endpoints[0].transportProfileUri);
 
 	response->endpoints[0].userIdentityTokensSize = 1;
-	UA_Array_new((void**) &response->endpoints[0].userIdentityTokens, response->endpoints[0].userIdentityTokensSize, UA_USERTOKENPOLICY);
+	UA_Array_new((void**) &response->endpoints[0].userIdentityTokens, response->endpoints[0].userIdentityTokensSize,
+				 &UA_.types[UA_USERTOKENPOLICY]);
 	UA_UserTokenPolicy *token = &response->endpoints[0].userIdentityTokens[0];
 	UA_String_copycstring("my-anonymous-policy", &token->policyId); // defined per server
 	token->tokenType = UA_USERTOKENTYPE_ANONYMOUS;

+ 1 - 1
src/ua_services_view.c

@@ -17,7 +17,7 @@ UA_Int32 Service_TranslateBrowsePathsToNodeIds(SL_Channel *channel, const UA_Tra
 
 	DBG_VERBOSE(printf("TranslateBrowsePathsToNodeIdsService - %i path(s)", request->browsePathsSize));
 	//Allocate space for a correct answer
-	UA_Array_new((void**)&response->results, request->browsePathsSize, UA_BROWSEPATHRESULT);
+	UA_Array_new((void**)&response->results, request->browsePathsSize, &UA_.types[UA_BROWSEPATHRESULT]);
 
 	response->resultsSize = request->browsePathsSize;
 

+ 5 - 5
src/ua_transport.c

@@ -433,14 +433,14 @@ UA_Int32 UA_SequenceHeader_copy(const UA_SequenceHeader *src,UA_SequenceHeader *
 UA_Int32 UA_SecureConversationMessageFooter_calcSizeBinary(UA_SecureConversationMessageFooter const * ptr) {
     	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageFooter);
     	return 0
-		+ UA_Array_calcSizeBinary(ptr->paddingSize,UA_BYTE,ptr->padding)
+		+ UA_Array_calcSizeBinary(ptr->paddingSize,&UA_.types[UA_BYTE],ptr->padding)
 	 + sizeof(UA_Byte) // signature
 	;
 }
 
 UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_ByteString* dst, UA_UInt32 *offset) {
     	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_encodeBinary(&src->padding,src->paddingSize,UA_BYTE,dst,offset);
+	retval |= UA_Array_encodeBinary(&src->padding,src->paddingSize,&UA_.types[UA_BYTE],dst,offset);
 	retval |= UA_Byte_encodeBinary(&src->signature,dst,offset);
 	return retval;
 }
@@ -449,7 +449,7 @@ UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * s
     	UA_Int32 retval = UA_SUCCESS;
 	UA_SecureConversationMessageFooter_init(dst);
 	CHECKED_DECODE(UA_Int32_decodeBinary(src,offset,&dst->paddingSize),UA_SecureConversationMessageFooter_deleteMembers(dst));
-	CHECKED_DECODE(UA_Array_decodeBinary(src,offset,dst->paddingSize,UA_BYTE,(void**)&dst->padding), UA_SecureConversationMessageFooter_deleteMembers(dst));
+	CHECKED_DECODE(UA_Array_decodeBinary(src,offset,dst->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding), UA_SecureConversationMessageFooter_deleteMembers(dst));
 	CHECKED_DECODE(UA_Byte_decodeBinary(src,offset,&dst->signature), UA_SecureConversationMessageFooter_deleteMembers(dst));
 	return retval;
 }
@@ -463,7 +463,7 @@ UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageF
 
 UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter *p) {
     	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_delete((void*)p->padding,p->paddingSize,UA_BYTE);
+	retval |= UA_Array_delete((void*)p->padding,p->paddingSize,&UA_.types[UA_BYTE]);
 	return retval;
 }
 
@@ -481,7 +481,7 @@ UA_Int32 UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMess
     	UA_Int32 retval = UA_SUCCESS;
 	memcpy(dst, src, sizeof(UA_SecureConversationMessageFooter));
 	dst->padding = src->padding;
-	retval |= UA_Array_copy(&src->padding, src->paddingSize,UA_BYTE,(void**)&dst->padding);
+	retval |= UA_Array_copy(&src->padding, src->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding);
 	return retval;
 }
 

+ 55 - 59
src/ua_types.c

@@ -630,15 +630,14 @@ UA_Int32 UA_Variant_deleteMembers(UA_Variant *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	if(p == UA_NULL) return retval;
 
+	UA_Boolean hasDimensions = p->arrayDimensions != UA_NULL;
+
 	if(p->data != UA_NULL) {
-		if(p->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY)
-			retval |= UA_Array_delete(p->data, p->arrayLength, UA_ns0ToVTableIndex(&p->vt->typeId));
-		else
-			retval |= p->vt->delete(p->data);
+		retval |= UA_Array_delete(p->data, p->arrayLength, p->vt);
 		p->data = UA_NULL;
 	}
-	if(p->arrayDimensions != UA_NULL) {
-		retval |= UA_Array_delete(p->arrayDimensions, p->arrayDimensionsLength, UA_INT32);
+	if(hasDimensions) {
+		UA_free(p->arrayDimensions);
 		p->arrayDimensions = UA_NULL;
 	}
 	return retval;
@@ -648,7 +647,6 @@ UA_Int32 UA_Variant_init(UA_Variant *p) {
 	if(p == UA_NULL) return UA_ERROR;
 	p->arrayLength  = -1; // no element, p->data == UA_NULL
 	p->data         = UA_NULL;
-	p->encodingMask = 0;
 	p->arrayDimensions       = UA_NULL;
 	p->arrayDimensionsLength = -1;
 	p->vt = &UA_.types[UA_INVALIDTYPE];
@@ -657,29 +655,18 @@ UA_Int32 UA_Variant_init(UA_Variant *p) {
 
 UA_TYPE_NEW_DEFAULT(UA_Variant)
 UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
-	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+	if(src == UA_NULL || dst == UA_NULL)
+		return UA_ERROR;
+
 	UA_Int32  retval = UA_SUCCESS;
-	// Variants are always with types from ns0 or an extensionobject.
-	UA_NodeId typeId =
-	{ UA_NODEIDTYPE_FOURBYTE, 0, .identifier.numeric = (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) };
-	UA_Int32  uaIdx  = UA_ns0ToVTableIndex(&typeId);
-	if(UA_VTable_isValidType(uaIdx) != UA_SUCCESS) return UA_ERROR;
-	dst->vt = &UA_.types[uaIdx];
+	dst->vt = src->vt;
 	retval |= UA_Int32_copy(&src->arrayLength, &dst->arrayLength);
-	retval |= UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
 	retval |= UA_Int32_copy(&src->arrayDimensionsLength, &dst->arrayDimensionsLength);
-
-	if(src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY)
-		retval |=  UA_Array_copy(src->data, src->arrayLength, uaIdx, &dst->data);
-	else {
-		UA_alloc(&dst->data, UA_.types[uaIdx].memSize);
-		UA_.types[uaIdx].copy(src->data, dst->data);
-	}
-
-	if(src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+	retval |=  UA_Array_copy(src->data, src->arrayLength, src->vt, &dst->data);
+	UA_Boolean hasDimensions = src->arrayDimensions != UA_NULL;
+	if(hasDimensions)
 		retval |= UA_Array_copy(src->arrayDimensions, src->arrayDimensionsLength,
-		                        UA_INT32, (void **)&dst->arrayDimensions);
-	}
+		                        &UA_.types[UA_INT32], (void **)&dst->arrayDimensions);
 	return retval;
 }
 
@@ -798,40 +785,28 @@ UA_Int32 UA_InvalidType_new(UA_InvalidType **p) {
 /* Array */
 /*********/
 
-UA_Int32 UA_Array_delete(void *p, UA_Int32 noElements, UA_Int32 type) {
-	UA_Int32 retval = UA_SUCCESS;
-	if(p == UA_NULL) return UA_SUCCESS;
-	char    *cp     = (char *)p; // so compilers allow pointer arithmetic
-	for(UA_Int32 i = 0;i < noElements;i++) {
-		retval |= UA_.types[type].deleteMembers(cp);
-		cp     += UA_.types[type].memSize;
-	}
-	UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_Int32 type) {
+UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_VTable_Entry *vt) {
+	if(vt == UA_NULL)
+		return UA_ERROR;
+			
 	if(noElements <= 0) {
 		*p = UA_NULL;
 		return UA_SUCCESS;
 	}
 
-	// FIXME!
-	// Arrays cannot be larger than 2**20
+	// FIXME! Arrays cannot be larger than 2**20.
 	// This was randomly chosen so that the development VM does not blow up.
 	if(noElements > 1048576) {
 		*p = UA_NULL;
 		return UA_ERROR;
 	}
 	
-	UA_Int32 retval = UA_VTable_isValidType(type);
-	if(retval != UA_SUCCESS) return retval;
-	retval = UA_alloc(p, UA_.types[type].memSize * noElements);
-	if(retval != UA_SUCCESS) {
-		*p = UA_NULL;
+	UA_Int32 retval = UA_SUCCESS;
+	retval = UA_alloc(p, vt->memSize * noElements);
+	if(retval != UA_SUCCESS)
 		return retval;
-	}
-	retval = UA_Array_init(*p, noElements, type);
+
+	retval = UA_Array_init(*p, noElements, vt);
 	if(retval != UA_SUCCESS) {
 		UA_free(*p);
 		*p = UA_NULL;
@@ -839,22 +814,42 @@ UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_Int32 type) {
 	return retval;
 }
 
-UA_Int32 UA_Array_init(void *p, UA_Int32 noElements, UA_Int32 type) {
+UA_Int32 UA_Array_init(void *p, UA_Int32 noElements, UA_VTable_Entry *vt) {
+	if(p == UA_NULL || vt == UA_NULL)
+		return UA_ERROR;
+
 	UA_Int32 retval = UA_SUCCESS;
 	char    *cp     = (char *)p; // so compilers allow pointer arithmetic
+	UA_UInt32 memSize = vt->memSize;
 	for(UA_Int32 i = 0;i < noElements && retval == UA_SUCCESS;i++) {
-		retval |= UA_.types[type].init(cp);
-		cp     += UA_.types[type].memSize;
+		retval |= vt->init(cp);
+		cp     += memSize;
 	}
 	return retval;
 }
 
-UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void **dst) {
-	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	if(UA_VTable_isValidType(type) != UA_SUCCESS)
+UA_Int32 UA_Array_delete(void *p, UA_Int32 noElements, UA_VTable_Entry *vt) {
+	if(p == UA_NULL)
+		return UA_SUCCESS;
+	if(vt == UA_NULL)
+		return UA_ERROR;
+
+	char    *cp     = (char *)p; // so compilers allow pointer arithmetic
+	UA_UInt32 memSize = vt->memSize;
+	UA_Int32 retval = UA_SUCCESS;
+	for(UA_Int32 i = 0;i < noElements;i++) {
+		retval |= vt->deleteMembers(cp);
+		cp     += memSize;
+	}
+	UA_free(p);
+	return retval;
+}
+
+UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, void **dst) {
+	if(src == UA_NULL || dst == UA_NULL || vt == UA_NULL)
 		return UA_ERROR;
 
-	UA_Int32 retval = UA_Array_new(dst, noElements, type);
+	UA_Int32 retval = UA_Array_new(dst, noElements, vt);
 	if(retval != UA_SUCCESS){
 		*dst = UA_NULL;
 		return retval;
@@ -862,16 +857,17 @@ UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void
 
 	char *csrc = (char *)src; // so compilers allow pointer arithmetic
 	char *cdst = (char *)*dst;
+	UA_UInt32 memSize = vt->memSize;
 	UA_Int32 i = 0;
 	for(;i < noElements && retval == UA_SUCCESS;i++) {
-		retval |= UA_.types[type].copy(csrc, cdst);
-		csrc   += UA_.types[type].memSize;
-		cdst   += UA_.types[type].memSize;
+		retval |= vt->copy(csrc, cdst);
+		csrc   += memSize;
+		cdst   += memSize;
 	}
 
 	if(retval != UA_SUCCESS) {
 		i--; // undo last increase
-		UA_Array_delete(*dst, i, type);
+		UA_Array_delete(*dst, i, vt);
 		*dst = UA_NULL;
 	}
 

+ 9 - 6
src/ua_types.h

@@ -172,7 +172,7 @@ typedef struct UA_VTable_Entry UA_VTable_Entry;
 /** @brief A union of all of the types specified above. */
 typedef struct UA_Variant {
 	UA_VTable_Entry *vt;          // internal entry into vTable
-	UA_Byte encodingMask;         // Type of UA_Variant_EncodingMaskType_enum
+	//UA_Byte encodingMask;       // Type of UA_Variant_EncodingMaskType_enum .. is generated, not set.
 	UA_Int32         arrayLength; // total number of elements
 	UA_Int32         arrayDimensionsLength;
 	UA_Int32        *arrayDimensions;
@@ -334,12 +334,12 @@ UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type, const void *dat
 UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_Int32 type, UA_Int32 arrayLength, const void *data);
 
 /* Array operations */
-UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_Int32 type);
-UA_Int32 UA_Array_init(void *p, UA_Int32 noElements, UA_Int32 type);
-UA_Int32 UA_Array_delete(void *p, UA_Int32 noElements, UA_Int32 type);
+UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_VTable_Entry *vt);
+UA_Int32 UA_Array_init(void *p, UA_Int32 noElements, UA_VTable_Entry *vt);
+UA_Int32 UA_Array_delete(void *p, UA_Int32 noElements, UA_VTable_Entry *vt);
 
 /* @brief The destination array is allocated according to noElements. */
-UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void **dst);
+UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, void **dst);
 
 /**********/
 /* VTable */
@@ -352,7 +352,7 @@ typedef UA_Int32 (*UA_calcSize)(const void *p);
 typedef UA_Int32 (*UA_encode)(const void *src, UA_ByteString *dst, UA_UInt32 *offset);
 
 /* @brief The decoding function decodes a ByteString into an UA datatype. */
-typedef UA_Int32 (*UA_decode)(UA_ByteString *src, UA_UInt32 *offset, void *dst);
+typedef UA_Int32 (*UA_decode)(const UA_ByteString *src, UA_UInt32 *offset, void *dst);
 
 typedef struct UA_Encoding {
 	UA_calcSize calcSize;
@@ -360,6 +360,9 @@ typedef struct UA_Encoding {
 	UA_decode   decode;
 } UA_Encoding;
 
+#define UA_ENCODING_BINARY 0
+#define UA_ENCODING_XML 1
+
 struct UA_VTable_Entry {
 	UA_NodeId   typeId;
 	UA_Byte    *name;

+ 160 - 148
src/ua_types_encoding_binary.c

@@ -5,47 +5,60 @@
 /* Array */
 /*********/
 
-UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_Int32 type, const void *data) {
-	if(UA_VTable_isValidType(type) != UA_SUCCESS) return 0;
-	UA_Int32 length = sizeof(UA_Int32);
-	const UA_Byte *cdata = (const UA_Byte *) data;
+UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_VTable_Entry *vt, const void *data) {
+	if(vt == UA_NULL || data == UA_NULL)
+		return UA_ERROR;
+
+	UA_Int32  length     = sizeof(UA_Int32);
+	UA_UInt32 memSize    = vt->memSize;
+	const UA_Byte *cdata = (const UA_Byte *)data;
 	for(UA_Int32 i = 0;i < nElements;i++) {
-		length += UA_.types[type].encodings[0].calcSize(cdata);
-		cdata += UA_.types[type].memSize;
+		length += vt->encodings[UA_ENCODING_BINARY].calcSize(cdata);
+		cdata  += memSize;
 	}
 	return length;
 }
 
-UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_Int32 type, UA_ByteString *dst, UA_UInt32 *offset) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, UA_ByteString *dst,
+                               UA_UInt32 *offset) {
+	if(vt == UA_NULL || src == UA_NULL || dst == UA_NULL || offset == UA_NULL)
+		return UA_ERROR;
+
+	UA_Int32 retval     = UA_SUCCESS;
 	retval = UA_Int32_encodeBinary(&noElements, dst, offset);
-	const UA_Byte *csrc = (const UA_Byte *) src;
-	for(UA_Int32 i = 0;i < noElements;i++) {
-		retval |= UA_.types[type].encodings[0].encode(csrc, dst, offset);
-		csrc += UA_.types[type].memSize;
+	const UA_Byte *csrc = (const UA_Byte *)src;
+	UA_UInt32 memSize   = vt->memSize;
+	for(UA_Int32 i = 0;i < noElements && retval == UA_SUCCESS;i++) {
+		retval |= vt->encodings[UA_ENCODING_BINARY].encode(csrc, dst, offset);
+		csrc   += memSize;
 	}
 	return retval;
 }
 
-UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_Int32 noElements, UA_Int32 type, void **dst) {
+UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements, UA_VTable_Entry *vt,
+                               void **dst) {
+	if(vt == UA_NULL || src == UA_NULL || dst == UA_NULL || offset == UA_NULL)
+		return UA_ERROR;
+
 	UA_Int32 retval = UA_SUCCESS;
 	if(noElements <= 0) {
 		*dst = UA_NULL;
 		return retval;
 	}
-	retval |= UA_Array_new(dst, noElements, type);
+	retval |= UA_Array_new(dst, noElements, vt);
 
-	UA_Byte *arr    = (UA_Byte *) *dst;
-	UA_Int32 i      = 0;
+	UA_Byte  *arr     = (UA_Byte *)*dst;
+	UA_Int32  i       = 0;
+	UA_UInt32 memSize = vt->memSize;
 	for(;i < noElements && retval == UA_SUCCESS;i++) {
-		retval |= UA_.types[type].encodings[0].decode((void *)src, offset, arr);
-		arr += UA_.types[type].memSize;
+		retval |= vt->encodings[UA_ENCODING_BINARY].decode(src, offset, arr);
+		arr    += memSize;
 	}
 
 	/* If dynamically sized elements have already been decoded into the array. */
 	if(retval != UA_SUCCESS) {
 		i--; // undo last increase
-		UA_Array_delete(*dst, i, type);
+		UA_Array_delete(*dst, i, vt);
 		*dst = UA_NULL;
 	}
 
@@ -56,30 +69,30 @@ UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_
 /* Built-In */
 /************/
 
-#define UA_TYPE_CALCSIZEBINARY_SIZEOF(TYPE)							\
-	UA_Int32 TYPE##_calcSizeBinary(TYPE const * p) { return sizeof(TYPE); }
+#define UA_TYPE_CALCSIZEBINARY_SIZEOF(TYPE) \
+    UA_Int32 TYPE##_calcSizeBinary(TYPE const *p) { return sizeof(TYPE); }
 
-#define UA_TYPE_ENCODEBINARY(TYPE, CODE)                                                \
+#define UA_TYPE_ENCODEBINARY(TYPE, CODE)                                                    \
     UA_Int32 TYPE##_encodeBinary(TYPE const *src, UA_ByteString * dst, UA_UInt32 *offset) { \
-		UA_Int32 retval = UA_SUCCESS;                                                   \
-		if((UA_Int32) (*offset + TYPE##_calcSizeBinary(src)) > dst->length ) { \
-			return UA_ERR_INVALID_VALUE;                                                \
-		} else {                                                                        \
-			CODE                                                                        \
-		}                                                                               \
-		return retval;                                                                  \
+		UA_Int32 retval = UA_SUCCESS;                                                       \
+		if((UA_Int32)(*offset + TYPE##_calcSizeBinary(src)) > dst->length ) {               \
+			return UA_ERR_INVALID_VALUE;                                                    \
+		} else {                                                                            \
+			CODE                                                                            \
+		}                                                                                   \
+		return retval;                                                                      \
 	}
 
 // Attention! this macro works only for TYPEs with memSize = encodingSize
-#define UA_TYPE_DECODEBINARY(TYPE, CODE)                                                \
+#define UA_TYPE_DECODEBINARY(TYPE, CODE)                                                    \
     UA_Int32 TYPE##_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, TYPE * dst) { \
-		UA_Int32 retval = UA_SUCCESS;                                                   \
-		if((UA_Int32) (*offset + TYPE##_calcSizeBinary(UA_NULL)) > src->length ) { \
-			return UA_ERR_INVALID_VALUE;                                                \
-		} else {                                                                        \
-			CODE                                                                        \
-		}                                                                               \
-		return retval;                                                                  \
+		UA_Int32 retval = UA_SUCCESS;                                                       \
+		if((UA_Int32)(*offset + TYPE##_calcSizeBinary(UA_NULL)) > src->length ) {           \
+			return UA_ERR_INVALID_VALUE;                                                    \
+		} else {                                                                            \
+			CODE                                                                            \
+		}                                                                                   \
+		return retval;                                                                      \
 	}
 
 /* Boolean */
@@ -87,7 +100,7 @@ UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Boolean)
 UA_TYPE_ENCODEBINARY(UA_Boolean,
                      UA_Boolean tmpBool = ((*src > 0) ? UA_TRUE : UA_FALSE);
                      memcpy(&dst->data[(*offset)++], &tmpBool, sizeof(UA_Boolean)); )
-UA_TYPE_DECODEBINARY(UA_Boolean, *dst = ((UA_Boolean)(src->data[(*offset)++]) > (UA_Byte) 0) ? UA_TRUE : UA_FALSE; )
+UA_TYPE_DECODEBINARY(UA_Boolean, *dst = ((UA_Boolean)(src->data[(*offset)++]) > (UA_Byte)0) ? UA_TRUE : UA_FALSE; )
 
 /* SByte */
 UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_SByte)
@@ -184,14 +197,14 @@ UA_TYPE_DECODEBINARY(UA_Float,
                      mantissa = (mantissa / 256.0 ) + (UA_Float)(src->data[*offset+1] & 0xFF); // bits 8-15
                      mantissa = (mantissa / 256.0 ) + (UA_Float)(src->data[*offset+2] & 0x7F); // bits 16-22
                      UA_UInt32 biasedExponent;
-                     biasedExponent  = (src->data[*offset+2] & 0x80) >>  7;                    // bits 23
-                     biasedExponent |= (src->data[*offset+3] & 0x7F) <<  1;                    // bits 24-30
+                     biasedExponent  = (src->data[*offset+2] & 0x80) >>  7;                   // bits 23
+                     biasedExponent |= (src->data[*offset+3] & 0x7F) <<  1;                   // bits 24-30
                      UA_Float sign = ( src->data[*offset+ 3] & 0x80 ) ? -1.0 : 1.0;           // bit 31
                      if(biasedExponent >= 127)
 						 *dst = (UA_Float)sign * (1 << (biasedExponent-127)) * (1.0 + mantissa / 128.0 );
                      else
 						 *dst = (UA_Float)sign * 2.0 * (1.0 + mantissa / 128.0 ) / ((UA_Float)(biasedExponent-127));
-                     *offset+= 4; )
+                     *offset += 4; )
 UA_TYPE_ENCODEBINARY(UA_Float, return UA_UInt32_encodeBinary((UA_UInt32 *)src, dst, offset); )
 
 /* Double */
@@ -221,7 +234,7 @@ UA_TYPE_DECODEBINARY(UA_Double,
 						 *dst = (UA_Double)sign * (1 << (biasedExponent-1023)) * (1.0 + mantissa / 8.0 );
                      else
 						 *dst = (UA_Double)sign * 2.0 * (1.0 + mantissa / 8.0 ) / ((UA_Double)(biasedExponent-1023));
-                     *offset+= 8; )
+                     *offset += 8; )
 UA_TYPE_ENCODEBINARY(UA_Double, return UA_UInt64_encodeBinary((UA_UInt64 *)src, dst, offset); )
 
 /* String */
@@ -238,11 +251,11 @@ UA_Int32 UA_String_calcSizeBinary(UA_String const *string) {
 UA_Int32 UA_String_encodeBinary(UA_String const *src, UA_ByteString *dst, UA_UInt32 *offset) {
 	UA_Int32 retval = UA_SUCCESS;
 	if(src == UA_NULL) return UA_ERR_INVALID_VALUE;
-	if((UA_Int32) (*offset+ UA_String_calcSizeBinary(src)) > dst->length) return UA_ERR_INVALID_VALUE;
+	if((UA_Int32)(*offset+ UA_String_calcSizeBinary(src)) > dst->length) return UA_ERR_INVALID_VALUE;
 	retval |= UA_Int32_encodeBinary(&src->length, dst, offset);
 	if(src->length > 0) {
-		retval |= UA_memcpy(&dst->data[*offset], src->data, src->length);
-		*offset+= src->length;
+		retval  |= UA_memcpy(&dst->data[*offset], src->data, src->length);
+		*offset += src->length;
 	}
 	return retval;
 }
@@ -259,7 +272,7 @@ UA_Int32 UA_String_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_
 		CHECKED_DECODE(UA_alloc((void **)&dst->data, dst->length), dst->length = -1);
 		CHECKED_DECODE(UA_memcpy(dst->data, &src->data[*offset], dst->length), UA_free(
 		                   dst->data); dst->data = UA_NULL; dst->length = -1);
-		*offset+= dst->length;
+		*offset += dst->length;
 	}
 	return retval;
 }
@@ -283,11 +296,11 @@ UA_TYPE_ENCODEBINARY(UA_Guid,
 						 CHECKED_DECODE(UA_Byte_encodeBinary(&src->data4[i], dst, offset),; ); )
 
 UA_TYPE_DECODEBINARY(UA_Guid,
-					 // TODO: This could be done with a single memcpy (if the compiler does no fancy realigning of structs)
-					 CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->data1),; );
-					 CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data2),; );
-					 CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data3),; );
-					 for(UA_Int32 i = 0;i < 8;i++)
+                     // TODO: This could be done with a single memcpy (if the compiler does no fancy realigning of structs)
+                     CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->data1),; );
+                     CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data2),; );
+                     CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data3),; );
+                     for(UA_Int32 i = 0;i < 8;i++)
 						 CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->data4[i]),; ); )
 
 /* ByteString */
@@ -373,10 +386,11 @@ UA_TYPE_ENCODEBINARY(UA_NodeId,
 						 retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
 						 retval |= UA_ByteString_encodeBinary(&src->identifier.byteString, dst, offset);
 						 break;
-					 })
+					 }
+                     )
 
 UA_Int32 UA_NodeId_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_NodeId *dst) {
-	UA_Int32  retval    = UA_SUCCESS;
+	UA_Int32 retval = UA_SUCCESS;
 	UA_NodeId_init(dst);
 	// temporary variables to overcome decoder's non-endian-saveness for datatypes with different length
 	UA_Byte   dstByte   = 0;
@@ -428,7 +442,7 @@ UA_Int32 UA_ExpandedNodeId_calcSizeBinary(UA_ExpandedNodeId const *p) {
 	else {
 		length = UA_NodeId_calcSizeBinary(&p->nodeId);
 		if(p->nodeId.encodingByte & UA_NODEIDTYPE_NAMESPACE_URI_FLAG)
-			length += UA_String_calcSizeBinary(&p->namespaceUri); //p->namespaceUri
+			length += UA_String_calcSizeBinary(&p->namespaceUri);  //p->namespaceUri
 		if(p->nodeId.encodingByte & UA_NODEIDTYPE_SERVERINDEX_FLAG)
 			length += sizeof(UA_UInt32);                    //p->serverIndex
 	}
@@ -504,7 +518,7 @@ UA_TYPE_ENCODEBINARY(UA_LocalizedText,
                      if(src->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
 						 retval |= UA_String_encodeBinary(&src->locale, dst, offset);
                      if(src->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
-						 retval |= UA_String_encodeBinary(&src->text, dst, offset);)
+						 retval |= UA_String_encodeBinary(&src->text, dst, offset); )
 
 UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_LocalizedText *dst) {
 	UA_Int32 retval = UA_SUCCESS;
@@ -550,13 +564,16 @@ UA_TYPE_ENCODEBINARY(UA_ExtensionObject,
 
 					 case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
 						 // FIXME: This code is valid for numeric nodeIds in ns0 only!
-						 retval |= UA_.types[UA_ns0ToVTableIndex(&src->typeId)].encodings[0].encode(src->body.data, dst, offset);
+						 retval |=
+						     UA_.types[UA_ns0ToVTableIndex(&src->typeId)].encodings[0].encode(src->body.data, dst,
+						                                                                      offset);
 						 break;
 
 					 case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
 						 retval |= UA_ByteString_encodeBinary(&src->body, dst, offset);
 						 break;
-					 })
+					 }
+                     )
 
 UA_Int32 UA_ExtensionObject_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_ExtensionObject *dst) {
 	UA_Int32 retval = UA_SUCCESS;
@@ -634,11 +651,11 @@ UA_Int32 UA_DataValue_calcSizeBinary(UA_DataValue const *p) {
 		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
 			length += sizeof(UA_UInt32);   //dataValue->status
 		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
-			length += sizeof(UA_DateTime); //dataValue->sourceTimestamp
+			length += sizeof(UA_DateTime);  //dataValue->sourceTimestamp
 		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
 			length += sizeof(UA_Int64);    //dataValue->sourcePicoseconds
 		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
-			length += sizeof(UA_DateTime); //dataValue->serverTimestamp
+			length += sizeof(UA_DateTime);  //dataValue->serverTimestamp
 		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
 			length += sizeof(UA_Int64);    //dataValue->serverPicoseconds
 	}
@@ -649,104 +666,88 @@ UA_Int32 UA_DataValue_calcSizeBinary(UA_DataValue const *p) {
 UA_Int32 UA_Variant_calcSizeBinary(UA_Variant const *p) {
 	if(p == UA_NULL)
 		return sizeof(UA_Variant);
-	// only ns0 supported.
-	// UA_UInt32  builtinNs0Id  = p->encodingMask & 0x3F;        // Bits 0-5
-	UA_Boolean isArray       = p->encodingMask & (0x01 << 7); // Bit 7
-	UA_Boolean hasDimensions = p->encodingMask & (0x01 << 6); // Bit 6
 
-	if(p->vt == UA_NULL || 0 != p->vt->typeId.namespace)
+	if(p->vt == UA_NULL)
 		return UA_ERR_INCONSISTENT;
 
-	UA_Int32   length        = 0;
-	length += sizeof(UA_Byte);      //p->encodingMask
-	if(isArray) {                   // array length is encoded
-		length += sizeof(UA_Int32); //p->arrayLength
-		if(p->arrayLength > 0) {
-			UA_Byte *cdata = (UA_Byte*)p->data;
-			for(UA_Int32 i = 0;i < p->arrayLength;i++) {
-				length += p->vt->encodings[0].calcSize(cdata);
-				cdata += p->vt->memSize;
-			}
-		}
-	} else { //single value to encode
-		if(p->data == UA_NULL) {
-			if(p->vt->typeId.identifier.numeric != UA_INVALIDTYPE_NS0)
-				length += p->vt->memSize;
-			else
-				length += 0;
-		} else {
-			length += p->vt->encodings[0].calcSize(p->data);
-		}
-	}
-	if(hasDimensions) {
-		//ToDo: tobeInsert: length += the calcSizeBinary for dimensions
+	UA_Boolean isArray = p->arrayLength != 1;       // a single element is not an array
+	UA_Boolean hasDimensions = isArray && p->arrayDimensions != UA_NULL;
+
+	UA_Int32   length        = sizeof(UA_Byte); //p->encodingMask
+	if(isArray) {
+		// array length + the array itself
+		length += UA_Array_calcSizeBinary(p->arrayLength, p->vt, p->data);
+	} else {
+		// if p->data is null, encoding will return an error anyway.
+		if(p->data != UA_NULL)
+			length += p->vt->encodings[UA_ENCODING_BINARY].calcSize(p->data);
 	}
+
+	if(hasDimensions)
+		length += UA_Array_calcSizeBinary(p->arrayDimensionsLength, &UA_.types[UA_INT32], p->arrayDimensions);
+
 	return length;
 }
 
 UA_TYPE_ENCODEBINARY(UA_Variant,
-                     if(src->vt == UA_NULL || ( src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) != src->vt->typeId.identifier.numeric) return UA_ERR_INCONSISTENT;
+                     if(src == UA_NULL || src->vt == UA_NULL || src->vt->typeId.namespace != 0)
+						 return UA_ERROR;
 
-                     retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
-                     if(src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY) // encode array length
-						 retval |= UA_Int32_encodeBinary(&src->arrayLength, dst, offset);
-                     if(src->arrayLength > 0) {
-                         //encode array as given by variant type
-						 UA_Byte *cdata = src->data;
-                         for(UA_Int32 i = 0;i < src->arrayLength;i++) {
-							 retval |= src->vt->encodings[0].encode(cdata, dst, offset);
-							 cdata += src->vt->memSize;
-						 }
-					 } else {
-                         if(src->data == UA_NULL) {
-                             if(src->vt->typeId.identifier.numeric == UA_INVALIDTYPE_NS0)
-								 retval = UA_SUCCESS;
-                             else
-								 retval = UA_ERR_NO_MEMORY;
-						 } else {
-							 retval |= src->vt->encodings[0].encode(src->data, dst, offset);
-						 }
-					 }
+                     UA_Boolean isArray       = src->arrayLength != 1;  // a single element is not an array
+                     UA_Boolean hasDimensions = isArray && src->arrayDimensions != UA_NULL;
 
-                     if(src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
-                         //encode dimension field
-                         UA_Int32_encodeBinary(&src->arrayDimensionsLength, dst, offset);
-                         if(src->arrayDimensionsLength > 0) {
-                             for(UA_Int32 i = 0;i < src->arrayDimensionsLength;i++)
-								 retval |= UA_Int32_encodeBinary(src->arrayDimensions + i, dst, offset);
-						 }
+                     UA_Byte encodingByte = 0;
+                     if(isArray) {
+                         encodingByte |= (0x01 << 7);
+                         if(hasDimensions)
+							 encodingByte |= (0x01 << 6);
+					 }
+                     encodingByte |= 0x3F & (UA_Byte)src->vt->typeId.identifier.numeric;;
+                     retval |= UA_Byte_encodeBinary(&encodingByte, dst, offset);
+
+                     if(isArray)
+						 retval |= UA_Array_encodeBinary(src->data, src->arrayLength, src->vt, dst, offset);
+                     else {
+                         if(src->data == UA_NULL)
+							 retval = UA_ERROR;       // an array can be empty. a single element must be present.
+                         retval |= src->vt->encodings[UA_ENCODING_BINARY].encode(src->data, dst, offset);
+					 }
 
-					 })
+                     if(hasDimensions)
+						 retval |= UA_Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsLength,
+						                                 &UA_.types[UA_INT32], dst, offset);
+                     )
 
-UA_Int32 UA_Variant_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_Variant *dst) {
+UA_Int32 UA_Variant_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_Variant * dst) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Variant_init(dst);
-	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingMask),; );
-	UA_NodeId typeid = {.encodingByte = (UA_Byte)UA_NODEIDTYPE_FOURBYTE, .namespace = 0, .identifier.numeric=dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK};
-
-	// initialize vTable
-	UA_Int32 uaIdx  = UA_ns0ToVTableIndex(&typeid);
-	if(UA_VTable_isValidType(uaIdx) != UA_SUCCESS)
-		return UA_ERROR;
-	dst->vt = &UA_.types[uaIdx];
-
-	// get size of array
-	if(dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY)    // get array length
-		CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->arrayLength),; );
-	else
+	
+	UA_Byte encodingByte;
+	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingByte),; );
+
+	UA_Boolean isArray = encodingByte & (0x01 << 7);                             // Bit 7
+	UA_Boolean hasDimensions = isArray && encodingByte & (0x01 << 6);            // Bit 6
+
+	UA_NodeId typeid = { .encodingByte = (UA_Byte)UA_NODEIDTYPE_FOURBYTE, .namespace= 0,
+						 .identifier.numeric = encodingByte & 0x3F };
+	UA_Int32 typeNs0Id = UA_ns0ToVTableIndex(&typeid );
+	dst->vt = &UA_.types[typeNs0Id];
+
+	if(isArray) {
+	CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->arrayLength),; );
+	CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, dst->vt,
+	                                     &dst->data), UA_Variant_deleteMembers(dst));
+	}else {
 		dst->arrayLength = 1;
-
-	if((dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) == UA_INVALIDTYPE_NS0) {  // handle NULL-Variant !
-		dst->data        = UA_NULL;
-		dst->arrayLength = -1;
-	} else {
-		// allocate array and decode
-		CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, uaIdx, &dst->data), UA_Variant_deleteMembers(dst));
+		UA_alloc(&dst->data, dst->vt->memSize);
+		dst->vt->encodings[UA_ENCODING_BINARY].decode(src, offset, dst->data);
 	}
+
 	//decode the dimension field array if present
-	if(dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+	if(hasDimensions) {
 		UA_Int32_decodeBinary(src, offset, &dst->arrayDimensionsLength);
-		CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, uaIdx,
+		CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayDimensionsLength,
+		                                     &UA_.types[UA_INT32],
 		                                     &dst->data), UA_Variant_deleteMembers(dst));
 	}
 	return retval;
@@ -759,7 +760,7 @@ UA_Int32 UA_DiagnosticInfo_calcSizeBinary(UA_DiagnosticInfo const *ptr) {
 		length = sizeof(UA_DiagnosticInfo);
 	else {
 		UA_Byte mask;
-		length += sizeof(UA_Byte);  // EncodingMask
+		length += sizeof(UA_Byte);                           // EncodingMask
 
 		for(mask = 0x01;mask <= 0x40;mask *= 2) {
 			switch(mask & (ptr->encodingMask)) {
@@ -798,7 +799,8 @@ UA_Int32 UA_DiagnosticInfo_calcSizeBinary(UA_DiagnosticInfo const *ptr) {
 	return length;
 }
 
-UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_DiagnosticInfo *dst) {
+UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset,
+                                        UA_DiagnosticInfo *dst) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_DiagnosticInfo_init(dst);
 	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingMask),; );
@@ -832,7 +834,8 @@ UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const *src, UA_UInt32 *off
 
 		case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
 			// innerDiagnosticInfo is a pointer to struct, therefore allocate
-			CHECKED_DECODE(UA_alloc((void **)&dst->innerDiagnosticInfo, UA_DiagnosticInfo_calcSizeBinary(UA_NULL)),; );
+			CHECKED_DECODE(UA_alloc((void **)&dst->innerDiagnosticInfo,
+			                        UA_DiagnosticInfo_calcSizeBinary(UA_NULL)),; );
 			CHECKED_DECODE(UA_DiagnosticInfo_decodeBinary(src, offset,
 			                                              dst->innerDiagnosticInfo),
 			               UA_DiagnosticInfo_deleteMembers(dst));
@@ -851,7 +854,8 @@ UA_TYPE_ENCODEBINARY(UA_DiagnosticInfo,
 							 break;
 
 						 case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
-							 retval |=  UA_Int32_encodeBinary( &src->namespaceUri, dst, offset);
+							 retval |=
+							     UA_Int32_encodeBinary( &src->namespaceUri, dst, offset);
 							 break;
 
 						 case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
@@ -863,20 +867,28 @@ UA_TYPE_ENCODEBINARY(UA_DiagnosticInfo,
 							 break;
 
 						 case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
-							 retval |= UA_String_encodeBinary(&src->additionalInfo, dst, offset);
+							 retval |=
+							     UA_String_encodeBinary(&src->additionalInfo, dst, offset);
 							 break;
 
 						 case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
-							 retval |= UA_StatusCode_encodeBinary(&src->innerStatusCode, dst, offset);
+							 retval |=
+							     UA_StatusCode_encodeBinary(&src->innerStatusCode, dst,
+							                                offset);
 							 break;
 
 						 case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
-							 retval |= UA_DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, dst, offset);
+							 retval |=
+							     UA_DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, dst,
+							                                    offset);
 							 break;
 						 }
-					 })
+					 }
+                     )
 
 /* InvalidType */
-UA_Int32 UA_InvalidType_calcSizeBinary(UA_InvalidType const *p) { return 0; }
+UA_Int32 UA_InvalidType_calcSizeBinary(UA_InvalidType const *p) {
+	return 0;
+}
 UA_TYPE_ENCODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )
 UA_TYPE_DECODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )

+ 3 - 5
src/ua_types_encoding_binary.h

@@ -97,15 +97,13 @@ UA_TYPE_BINARY_ENCODING(UA_InvalidType)
 /*********/
 
 /* Computes the size of an array (incl. length field) in a binary blob. */
-UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_Int32 type, const void *data);
+UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_VTable_Entry *vt, const void *data);
 
 /* @brief Encodes an array into a binary blob. The array size is printed as well. */
-UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_Int32 type, UA_ByteString *dst,
-                               UA_UInt32 *offset);
+UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, UA_ByteString *dst, UA_UInt32 *offset);
 
 /* @brief Decodes an array from a binary blob. The array is allocated automatically before decoding. */
-UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements, UA_Int32 type,
-                               void **dst);
+UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_Int32 noElements, UA_VTable_Entry *vt, void **dst);
 
 /// @} /* end of group */
 

+ 0 - 2
src/ua_types_encoding_xml.c

@@ -423,7 +423,6 @@ UA_Int32 UA_Variant_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_Variant
 			dst->arrayLength  = array->size;
 			dst->data         = array->elements;
 			dst->vt = &UA_.types[UA_EXTENSIONOBJECT];
-			dst->encodingMask = UA_EXTENSIONOBJECT_NS0 & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		} else if(s->parent[s->depth - 1].activeChild == 1 && attr != UA_NULL ) {  // LocalizedText
 			UA_TypedArray *array = (UA_TypedArray *)attr;
@@ -432,7 +431,6 @@ UA_Int32 UA_Variant_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_Variant
 			dst->arrayLength  = array->size;
 			dst->data         = array->elements;
 			dst->vt = &UA_.types[UA_LOCALIZEDTEXT];
-			dst->encodingMask = UA_LOCALIZEDTEXT_NS0 & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
 	}

+ 14 - 23
tests/check_builtin.c

@@ -458,7 +458,7 @@ END_TEST
 START_TEST(UA_Variant_calcSizeFixedSizeArrayShallReturnEncodingSize) {
 	// given
 	UA_Variant arg;
-	arg.encodingMask = UA_INT32_NS0 | UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	UA_Variant_init(&arg);
 	arg.vt = &UA_.types[UA_INT32];
 #define ARRAY_LEN 8
 	arg.arrayLength = ARRAY_LEN;
@@ -476,7 +476,7 @@ END_TEST
 START_TEST(UA_Variant_calcSizeVariableSizeArrayShallReturnEncodingSize) {
 	// given
 	UA_Variant arg;
-	arg.encodingMask = UA_STRING_NS0 | UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	UA_Variant_init(&arg);
 	arg.vt = &UA_.types[UA_STRING];
 #define ARRAY_LEN 3
 	arg.arrayLength = ARRAY_LEN;
@@ -850,7 +850,6 @@ START_TEST(UA_Variant_decodeWithOutArrayFlagSetShallSetVTAndAllocateMemoryForArr
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(pos, 5);
-	ck_assert_uint_eq(dst.encodingMask, UA_INT32_NS0);
 	ck_assert_ptr_eq(dst.vt, &UA_.types[UA_INT32]);
 	ck_assert_int_eq(dst.arrayLength, 1);
 	ck_assert_ptr_eq(dst.data, UA_alloc_lastptr);
@@ -874,8 +873,6 @@ START_TEST(UA_Variant_decodeWithArrayFlagSetShallSetVTAndAllocateMemoryForArray)
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(pos, 1+4+2*4);
-	ck_assert_uint_eq(dst.encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK, UA_INT32_NS0);
-	ck_assert_uint_eq(dst.encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY, UA_VARIANT_ENCODINGMASKTYPE_ARRAY);
 	ck_assert_ptr_eq(dst.vt, &UA_.types[UA_INT32]);
 	ck_assert_int_eq(dst.arrayLength, 2);
 	ck_assert_ptr_eq(dst.data, UA_alloc_lastptr);
@@ -1299,9 +1296,9 @@ START_TEST(UA_DataValue_encodeShallWorkOnExampleWithVariant) {
 	UA_DataValue src;
 	src.serverTimestamp    = 80;
 	src.encodingMask       = UA_DATAVALUE_ENCODINGMASK_VARIANT | UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP; //Variant & SourvePicoseconds
+	UA_Variant_init(&src.value);
 	src.value.vt           = &UA_.types[UA_INT32];
-	src.value.arrayLength  = 0;
-	src.value.encodingMask = UA_INT32_NS0;
+	src.value.arrayLength  = 1; // one element (encoded as not an array)
 	UA_Int32  vdata  = 45;
 	src.value.data = (void *)&vdata;
 
@@ -1419,7 +1416,7 @@ START_TEST(UA_Array_copyByteArrayShallWorkOnExample) {
 	testString.length  = 5;
 
 	//when
-	UA_Array_copy((const void *)testString.data, 5, UA_BYTE, (void **)&dstArray);
+	UA_Array_copy((const void *)testString.data, 5, &UA_.types[UA_BYTE], (void **)&dstArray);
 	//then
 	for(i = 0;i < size;i++)
 		ck_assert_int_eq(testString.data[i], dstArray[i]);
@@ -1435,14 +1432,14 @@ START_TEST(UA_Array_copyUA_StringShallWorkOnExample) {
 	// given
 	UA_Int32   i, j;
 	UA_String *srcArray;
-	UA_Array_new((void **)&srcArray, 3, UA_STRING);
+	UA_Array_new((void **)&srcArray, 3, &UA_.types[UA_STRING]);
 	UA_String *dstArray;
 
 	UA_String_copycstring("open", &srcArray[0]);
 	UA_String_copycstring("62541", &srcArray[1]);
 	UA_String_copycstring("opc ua", &srcArray[2]);
 	//when
-	UA_Array_copy((const void *)srcArray, 3, UA_STRING, (void **)&dstArray);
+	UA_Array_copy((const void *)srcArray, 3, &UA_.types[UA_STRING], (void **)&dstArray);
 	//then
 	for(i = 0;i < 3;i++) {
 		for(j = 0;j < 3;j++)
@@ -1450,8 +1447,8 @@ START_TEST(UA_Array_copyUA_StringShallWorkOnExample) {
 		ck_assert_int_eq(srcArray[i].length, dstArray[i].length);
 	}
 	//finally
-	UA_Array_delete(srcArray, 3, UA_STRING);
-	UA_Array_delete(dstArray, 3, UA_STRING);
+	UA_Array_delete(srcArray, 3, &UA_.types[UA_STRING]);
+	UA_Array_delete(dstArray, 3, &UA_.types[UA_STRING]);
 }
 END_TEST
 
@@ -1554,8 +1551,8 @@ START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 	UA_Variant_init(&copiedValue);
 	UA_alloc((void**)&value.data, sizeof(UA_String));
 	*((UA_String*)value.data) = testString;
-	value.encodingMask = UA_STRING_NS0;
 	value.vt = &UA_.types[UA_STRING];
+	value.arrayLength = 1;
 
 	//when
 	UA_Variant_copy(&value, &copiedValue);
@@ -1566,7 +1563,6 @@ START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 		ck_assert_int_eq(copiedString.data[i], testString.data[i]);
 	ck_assert_int_eq(copiedString.length, testString.length);
 
-	ck_assert_int_eq(value.encodingMask, copiedValue.encodingMask);
 	ck_assert_int_eq(value.arrayDimensionsLength, copiedValue.arrayDimensionsLength);
 	ck_assert_int_eq(value.arrayLength, copiedValue.arrayLength);
 
@@ -1580,7 +1576,7 @@ END_TEST
 START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
 	// given
 	UA_String *srcArray;
-	UA_Array_new((void **)&srcArray, 3, UA_STRING);
+	UA_Array_new((void **)&srcArray, 3, &UA_.types[UA_STRING]);
 	UA_String_copycstring("__open", &srcArray[0]);
 	UA_String_copycstring("_62541", &srcArray[1]);
 	UA_String_copycstring("opc ua", &srcArray[2]);
@@ -1597,8 +1593,6 @@ START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
 	value.data        = (void **)srcArray;
 	value.arrayDimensionsLength = 1;
 	value.arrayDimensions       = dimensions;
-	value.encodingMask          = UA_VARIANT_ENCODINGMASKTYPE_ARRAY | UA_STRING_NS0 |
-	                              UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
 	value.vt = &UA_.types[UA_STRING];
 
 	//when
@@ -1617,7 +1611,6 @@ START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
 	ck_assert_int_eq(((UA_String *)copiedValue.data)[0].data[2], 'o');
 	ck_assert_int_eq(((UA_String *)copiedValue.data)[0].data[3], 'p');
 
-	ck_assert_int_eq(value.encodingMask, copiedValue.encodingMask);
 	ck_assert_int_eq(value.arrayDimensionsLength, copiedValue.arrayDimensionsLength);
 	ck_assert_int_eq(value.arrayLength, copiedValue.arrayLength);
 
@@ -1630,7 +1623,7 @@ END_TEST
 START_TEST(UA_Variant_copyShallWorkOn2DArrayExample) {
 	// given
 	UA_Int32 *srcArray;
-	UA_Array_new((void **)&srcArray, 6, UA_INT32);
+	UA_Array_new((void **)&srcArray, 6, &UA_.types[UA_INT32]);
 	srcArray[0] = 0;
 	srcArray[1] = 1;
 	srcArray[2] = 2;
@@ -1639,7 +1632,7 @@ START_TEST(UA_Variant_copyShallWorkOn2DArrayExample) {
 	srcArray[5] = 5;
 
 	UA_Int32 *dimensions;
-	UA_Array_new((void **)&dimensions, 2, UA_INT32);
+	UA_Array_new((void **)&dimensions, 2, &UA_.types[UA_INT32]);
 	UA_Int32  dim1 = 3;
 	UA_Int32  dim2 = 2;
 	dimensions[0] = dim1;
@@ -1653,8 +1646,7 @@ START_TEST(UA_Variant_copyShallWorkOn2DArrayExample) {
 	value.data        = (void **)srcArray;
 	value.arrayDimensionsLength = 2;
 	value.arrayDimensions       = dimensions;
-	value.encodingMask         |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY | UA_INT32_NS0 |
-	                              UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
+	value.vt = &UA_.types[UA_INT32];
 
 	//when
 	UA_Variant_copy(&value, &copiedValue);
@@ -1681,7 +1673,6 @@ START_TEST(UA_Variant_copyShallWorkOn2DArrayExample) {
 		ck_assert_int_eq(i2, i);
 	}
 
-	ck_assert_int_eq(value.encodingMask, copiedValue.encodingMask);
 	ck_assert_int_eq(value.arrayDimensionsLength, copiedValue.arrayDimensionsLength);
 	ck_assert_int_eq(value.arrayLength, copiedValue.arrayLength);
 

+ 38 - 25
tests/check_memory.c

@@ -27,7 +27,7 @@ START_TEST(arrayCopyShallMakeADeepCopy) {
 	a1[2] = (UA_String){3, (UA_Byte*)"ccc"};
 	// when
 	UA_String *a2;
-	UA_Int32   retval = UA_Array_copy((const void *)a1, 3, UA_STRING, (void **)&a2);
+	UA_Int32   retval = UA_Array_copy((const void *)a1, 3, &UA_.types[UA_STRING], (void **)&a2);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(a1[0].length, 1);
@@ -43,7 +43,7 @@ START_TEST(arrayCopyShallMakeADeepCopy) {
 	ck_assert_int_eq(a1[1].data[0], a2[1].data[0]);
 	ck_assert_int_eq(a1[2].data[0], a2[2].data[0]);
 	// finally
-	UA_Array_delete((void *)a2, 3, UA_STRING);
+	UA_Array_delete((void *)a2, 3, &UA_.types[UA_STRING]);
 }
 END_TEST
 
@@ -55,15 +55,26 @@ START_TEST(encodeShallYieldDecode) {
 	UA_UInt32     pos = 0;
 	retval = UA_.types[_i].new(&obj1);
 	UA_ByteString_newMembers(&msg1, UA_.types[_i].encodings[0].calcSize(obj1));
-	retval = UA_.types[_i].encodings[0].encode(obj1, &msg1, &pos);
+	retval |= UA_.types[_i].encodings[UA_ENCODING_BINARY].encode(obj1, &msg1, &pos);
+	if(retval != UA_SUCCESS) {
+		// this happens, e.g. when we encode a variant (with UA_.types[UA_INVALIDTYPE] in the vtable)
+		UA_.types[_i].delete(obj1);
+		UA_ByteString_deleteMembers(&msg1);
+		return;	
+	}
+
 	// when
 	UA_.types[_i].new(&obj2);
-	pos = 0; retval = UA_.types[_i].encodings[0].decode(&msg1, &pos, obj2);
-	UA_ByteString_newMembers(&msg2, UA_.types[_i].encodings[0].calcSize(obj2));
-	pos = 0; retval = UA_.types[_i].encodings[0].encode(obj2, &msg2, &pos);
+	pos = 0; retval = UA_.types[_i].encodings[UA_ENCODING_BINARY].decode(&msg1, &pos, obj2);
+	ck_assert_msg(retval == UA_SUCCESS, "messages differ idx=%d,name=%s", _i, UA_.types[_i].name);
+	retval = UA_ByteString_newMembers(&msg2, UA_.types[_i].encodings[UA_ENCODING_BINARY].calcSize(obj2));
+	ck_assert_int_eq(retval, UA_SUCCESS);
+	pos = 0; retval = UA_.types[_i].encodings[UA_ENCODING_BINARY].encode(obj2, &msg2, &pos);
+	ck_assert_int_eq(retval, UA_SUCCESS);
+
 	// then
 	ck_assert_msg(UA_ByteString_equal(&msg1, &msg2) == 0, "messages differ idx=%d,name=%s", _i, UA_.types[_i].name);
-	ck_assert_int_eq(retval, UA_SUCCESS);
+
 	// finally
 	UA_.types[_i].delete(obj1);
 	UA_.types[_i].delete(obj2);
@@ -74,7 +85,7 @@ END_TEST
 
 START_TEST(decodeShallFailWithTruncatedBufferButSurvive) {
 	// given
-	void    *obj1 = UA_NULL, *obj2 = UA_NULL;
+	void *obj1 = UA_NULL, *obj2 = UA_NULL;
 	UA_ByteString msg1;
 	UA_UInt32 pos;
 	UA_.types[_i].new(&obj1);
@@ -97,17 +108,16 @@ END_TEST
 
 START_TEST(decodeScalarBasicTypeFromRandomBufferShallSucceed) {
 	// given
-	void    *obj1 = UA_NULL;
+	void *obj1 = UA_NULL;
 	UA_ByteString msg1;
-	UA_Int32 retval, buflen;
-	buflen = 256;
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 buflen = 256;
 	UA_ByteString_newMembers(&msg1, buflen); // fixed size
 	srandom(42);
-	retval = UA_SUCCESS;
-	for(int n = 0;n < 100;n++) {
-		retval |= UA_.types[_i].new(&obj1);
-		UA_Int32 i; for(i = 0;i < buflen;i++) msg1.data[i] = (UA_Byte)random();  // when
+	for(int n = 0;n < 1000;n++) {
+		for(UA_Int32 i = 0;i < buflen;i++) msg1.data[i] = (UA_Byte)random();  // when
 		UA_UInt32 pos = 0;
+		retval |= UA_.types[_i].new(&obj1);
 		retval |= UA_.types[_i].encodings[0].decode(&msg1, &pos, obj1);
 		//then
 		ck_assert_msg(retval == UA_SUCCESS, "Decoding %s from random buffer", UA_.types[_i].name);
@@ -122,21 +132,24 @@ START_TEST(decodeComplexTypeFromRandomBufferShallSurvive) {
 	// given
 	void    *obj1 = UA_NULL;
 	UA_ByteString msg1;
-	UA_Int32 retval, buflen;
-	buflen = 256;
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 buflen = 256;
 	UA_ByteString_newMembers(&msg1, buflen); // fixed size
 	srandom(42);
-	retval = UA_SUCCESS;
-	for(int n = 0;n < 100;n++) {
-		retval |= UA_.types[_i].new(&obj1);
-		UA_Int32 i; for(i = 0;i < buflen;i++) msg1.data[i] = (UA_Byte)random();  // when
+	// when
+	for(int n = 0;n < 1000;n++) {
+		for(UA_Int32 i = 0;i < buflen;i++) msg1.data[i] = (UA_Byte)random();
 		UA_UInt32 pos = 0;
+		retval |= UA_.types[_i].new(&obj1);
 		retval |= UA_.types[_i].encodings[0].decode(&msg1, &pos, obj1);
-		//then
-		ck_assert_msg(retval == UA_SUCCESS || retval != UA_SUCCESS, "Decoding %s from random buffer", UA_.types[_i].name);
-		// finally
+
+		//this is allowed to fail and return UA_ERROR
+		//ck_assert_msg(retval == UA_SUCCESS, "Decoding %s from random buffer", UA_.types[_i].name);
+		
 		UA_.types[_i].delete(obj1);
 	}
+
+	// finally
 	UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST
@@ -163,7 +176,7 @@ int main() {
 
 	sr = srunner_create(s);
 	//for debugging puposes only, will break make check
-	// srunner_set_fork_status(sr, CK_NOFORK);
+	//srunner_set_fork_status(sr, CK_NOFORK);
 	srunner_run_all (sr, CK_NORMAL);
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);

+ 1 - 1
tests/check_services_view.c

@@ -25,7 +25,7 @@ START_TEST(Service_TranslateBrowsePathsToNodeIds_SmokeTest)
 	UA_TranslateBrowsePathsToNodeIdsResponse_init(&response);
 
 	request.browsePathsSize = 1;
-	UA_Array_new((void**)&request.browsePaths,request.browsePathsSize, UA_BROWSEPATH);
+	UA_Array_new((void**)&request.browsePaths,request.browsePathsSize, &UA_.types[UA_BROWSEPATH]);
 
 	Service_TranslateBrowsePathsToNodeIds(UA_NULL,&request,&response);
 

+ 10 - 9
tools/generate_builtin.py

@@ -151,7 +151,8 @@ def createStructured(element):
         if t in fixed_size:
             printc('\t + sizeof(%(t)s) // %(n)s')
         elif t.find("*") != -1:
-            printc('\t + UA_Array_calcSizeBinary(ptr->%(n)sSize,'+ t[0:t.find("*")].upper() + ",ptr->%(n)s)")
+            printc('\t + UA_Array_calcSizeBinary(ptr->%(n)sSize,&UA_.types['+ t[0:t.find("*")].upper() +
+                   "],ptr->%(n)s)")
             has_fixed_size = False
         else:
             printc('\t + %(t)s_calcSizeBinary(&ptr->%(n)s)')
@@ -165,8 +166,8 @@ def createStructured(element):
     \tUA_Int32 retval = UA_SUCCESS;''')
     for n,t in membermap.iteritems():
         if t.find("*") != -1:
-            printc("\tretval |= UA_Array_encodeBinary(src->%(n)s,src->%(n)sSize," +
-                   t[0:t.find("*")].upper() + ",dst,offset);")
+            printc("\tretval |= UA_Array_encodeBinary(src->%(n)s,src->%(n)sSize,&UA_.types[" +
+                   t[0:t.find("*")].upper() + "],dst,offset);")
         else:
             printc('\tretval |= %(t)s_encodeBinary(&src->%(n)s,dst,offset);')
     printc("\treturn retval;\n}\n")
@@ -179,8 +180,8 @@ def createStructured(element):
         if t.find("*") != -1:
             printc('\tCHECKED_DECODE(UA_Int32_decodeBinary(src,offset,&dst->%(n)sSize),' +
                    '%(name)s_deleteMembers(dst));')
-            printc('\tCHECKED_DECODE(UA_Array_decodeBinary(src,offset,dst->%(n)sSize,' + t[0:t.find("*")].upper() +
-                   ',(void**)&dst->%(n)s), %(name)s_deleteMembers(dst));')
+            printc('\tCHECKED_DECODE(UA_Array_decodeBinary(src,offset,dst->%(n)sSize,&UA_.types[' +
+                   t[0:t.find("*")].upper() + '],(void**)&dst->%(n)s), %(name)s_deleteMembers(dst));')
         else:
             printc('\tCHECKED_DECODE(%(t)s_decodeBinary(src,offset,&dst->%(n)s), %(name)s_deleteMembers(dst));')
     printc("\treturn retval;\n}\n")
@@ -203,8 +204,8 @@ def createStructured(element):
     for n,t in membermap.iteritems():
         if not t in fixed_size: # dynamic size on the wire
             if t.find("*") != -1:
-		printc("\tretval |= UA_Array_delete((void*)p->%(n)s,p->%(n)sSize," +
-                       t[0:t.find("*")].upper()+");")
+		printc("\tretval |= UA_Array_delete((void*)p->%(n)s,p->%(n)sSize,&UA_.types[" +
+                       t[0:t.find("*")].upper()+"]);")
             else:
 		printc('\tretval |= %(t)s_deleteMembers(&p->%(n)s);')
     printc("\treturn retval;\n}\n")
@@ -231,8 +232,8 @@ def createStructured(element):
     for n,t in membermap.iteritems():
         if t.find("*") != -1:
             printc('\tdst->%(n)s = src->%(n)s;')
-            printc("\tretval |= UA_Array_copy(src->%(n)s, src->%(n)sSize," +
-                      t[0:t.find("*")].upper()+",(void**)&dst->%(n)s);")
+            printc("\tretval |= UA_Array_copy(src->%(n)s, src->%(n)sSize,&UA_.types[" +
+                      t[0:t.find("*")].upper()+"],(void**)&dst->%(n)s);")
             continue
         if not t in fixed_size: # there are members of variable size    
             printc('\tretval |= %(t)s_copy(&src->%(n)s,&dst->%(n)s);')

+ 1 - 1
tools/generate_namespace.py

@@ -97,7 +97,7 @@ printc('''/**********************************************************
  **********************************************************/\n
 #include "''' + sys.argv[2] + '''.h"\n
 UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
-	UA_Int32 retval = UA_ERR_INVALID_VALUE;
+	UA_Int32 retval = 0; // InvalidType
         if(id->namespace != 0) return retval;
 	switch (id->identifier.numeric) {''')