Selaa lähdekoodia

refactoring .. bigger than expected

Julius Pfrommer 10 vuotta sitten
vanhempi
commit
0af770f6fa
48 muutettua tiedostoa jossa 22437 lisäystä ja 3198 poistoa
  1. 3 2
      Makefile.am
  2. 1 1
      configure.ac
  3. 115 45
      examples/src/xml2ns0.c
  4. 0 8
      include/Makefile.am
  5. 0 490
      include/ua_basictypes.h
  6. 0 0
      schema/NodeIds.csv
  7. 0 0
      schema/Opc.Ua.NodeSet2.Part3.xml
  8. 0 0
      schema/Opc.Ua.NodeSet2.Part4.xml
  9. 0 0
      schema/Opc.Ua.NodeSet2.Part5.xml
  10. 0 0
      schema/Opc.Ua.NodeSet2.xml
  11. 0 0
      schema/Opc.Ua.Types.bsd
  12. 0 0
      schema/UA_stackInternalTypes.bsd
  13. 15 5
      src/Makefile.am
  14. 3 3
      src/ua_application.c
  15. 1 1
      src/ua_application.h
  16. 0 1691
      src/ua_basictypes.c
  17. 1 1
      include/ua_indexedList.h
  18. 1 1
      include/ua_list.h
  19. 2 2
      src/ua_namespace.h
  20. 1 1
      src/ua_services.h
  21. 59 59
      src/ua_services_attribute.c
  22. 12 12
      src/ua_services_discovery.c
  23. 9 9
      src/ua_services_nodemanagement.c
  24. 5 7
      src/ua_services_view.c
  25. 1 1
      include/ua_statuscodes.h
  26. 314 237
      src/ua_transport.c
  27. 34 90
      src/ua_transport.h
  28. 12 14
      src/ua_transport_binary.c
  29. 1 1
      src/ua_transport_binary.h
  30. 35 36
      src/ua_transport_binary_secure.c
  31. 3 3
      src/ua_transport_binary_secure.h
  32. 812 0
      src/ua_types.c
  33. 417 0
      src/ua_types.h
  34. 880 0
      src/ua_types_encoding_binary.c
  35. 79 0
      src/ua_types_encoding_binary.h
  36. 153 0
      src/ua_types_encoding_xml.c
  37. 65 0
      src/ua_types_encoding_xml.h
  38. 15835 0
      src/ua_types_generated.c
  39. 3028 0
      src/ua_types_generated.h
  40. 60 0
      src/ua_util.h
  41. 138 141
      src/ua_xml.c
  42. 50 46
      src/ua_xml.h
  43. 35 0
      src/ua_xml_namespace.h
  44. 1 0
      src/util/ua_indexedList.c
  45. 1 0
      src/util/ua_list.c
  46. 0 25
      tools/Makefile.am
  47. 195 229
      tools/generate_builtin.py
  48. 60 37
      tools/generate_namespace.py

+ 3 - 2
Makefile.am

@@ -1,4 +1,5 @@
-AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -Wl,-z,relro -Wl,-z,now -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
+#AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -Wl,-z,relro -Wl,-z,now -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
+AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
 AM_LDFLAGS =
 AM_LDADD =
 
@@ -20,7 +21,7 @@ endif
 export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 export GLOBAL_AM_LDADD = $(AM_LDADD)
 
-SUBS=tools include src
+SUBS=src
 if HAVE_CHECK
 	SUBS+= tests
 endif

+ 1 - 1
configure.ac

@@ -100,6 +100,6 @@ AM_COND_IF([ENABLE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
 AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
 AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_FILES(Makefile include/Makefile src/Makefile tools/Makefile tests/Makefile examples/src/Makefile doc/Makefile)
+AC_CONFIG_FILES(Makefile src/Makefile tests/Makefile examples/src/Makefile doc/Makefile)
 AC_OUTPUT
 

+ 115 - 45
examples/src/xml2ns0.c

@@ -1,11 +1,92 @@
-/*
- * xml2ns0.c
+#include <fcntl.h> // open, O_RDONLY
+#include "ua_types.h"
+#include "ua_types_generated.h"
+#include "ua_namespace.h"
+#include "ua_xml.h"
+#include "ua_xml_namespace.h"
+
+typedef UA_Int32 (*XML_Stack_Loader) (char* buf, int len);
+
+#define XML_BUFFER_LEN 1024
+UA_Int32 Namespace_loadXml(Namespace **ns,UA_UInt32 nsid,const char* rootName, XML_Stack_Loader getNextBufferFull) {
+	UA_Int32 retval = UA_SUCCESS;
+	char buf[XML_BUFFER_LEN];
+	int len; /* len is the number of bytes in the current bufferful of data */
+
+	XML_Stack s;
+	XML_Stack_init(&s, rootName);
+
+	UA_NodeSet n;
+	UA_NodeSet_init(&n, 0);
+	*ns = n.ns;
+
+	XML_Stack_addChildHandler(&s, "UANodeSet", strlen("UANodeSet"), (XML_decoder) UA_NodeSet_decodeXML, UA_INVALIDTYPE, &n);
+	XML_Parser parser = XML_ParserCreate(NULL);
+	XML_SetUserData(parser, &s);
+	XML_SetElementHandler(parser, XML_Stack_startElement, XML_Stack_endElement);
+	XML_SetCharacterDataHandler(parser, XML_Stack_handleText);
+	while ((len = getNextBufferFull(buf, XML_BUFFER_LEN)) > 0) {
+		if (XML_Parse(parser, buf, len, (len < XML_BUFFER_LEN)) == XML_STATUS_ERROR) {
+			retval = UA_ERR_INVALID_VALUE;
+			break;
+		}
+	}
+	XML_ParserFree(parser);
+
+	DBG_VERBOSE(printf("Namespace_loadXml - aliases addr=%p, size=%d\n", (void*) &(n.aliases), n.aliases.size));
+	DBG_VERBOSE(UA_NodeSetAliases_println("Namespace_loadXml - elements=", &n.aliases));
+
+	return retval;
+}
+
+static int theFile = 0;
+UA_Int32 readFromTheFile(char*buf,int len) {
+	return read(theFile,buf,len);
+}
+
+/** @brief load a namespace from an XML-File
  *
- *  Created on: 21.04.2014
- *      Author: mrt
+ * @param[in/out] ns the address of the namespace ptr
+ * @param[in] namespaceId the numeric id of the namespace
+ * @param[in] rootName the name of the root element of the hierarchy (not used?)
+ * @param[in] fileName the name of an existing file, e.g. Opc.Ua.NodeSet2.xml
  */
+UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 nsid,const char* rootName,const char* fileName) {
+	if (fileName == UA_NULL)
+		theFile = 0; // stdin
+	else if ((theFile = open(fileName, O_RDONLY)) == -1)
+		return UA_ERR_INVALID_VALUE;
 
-#include "ua_xml.h"
+	UA_Int32 retval = Namespace_loadXml(ns,nsid,rootName,readFromTheFile);
+	close(theFile);
+	return retval;
+}
+
+static const char* theBuffer = UA_NULL;
+static const char* theBufferEnd = UA_NULL;
+UA_Int32 readFromTheBuffer(char*buf,int len) {
+	if (len == 0) return 0;
+	if (theBuffer + XML_BUFFER_LEN > theBufferEnd)
+		len = theBufferEnd - theBuffer + 1;
+	else
+		len = XML_BUFFER_LEN;
+	memcpy(buf,theBuffer,len);
+	theBuffer = theBuffer + len;
+	return len;
+}
+
+/** @brief load a namespace from a string
+ *
+ * @param[in/out] ns the address of the namespace ptr
+ * @param[in] namespaceId the numeric id of the namespace
+ * @param[in] rootName the name of the root element of the hierarchy (not used?)
+ * @param[in] buffer the xml string
+ */
+UA_Int32 Namespace_loadFromString(Namespace **ns,UA_UInt32 nsid,const char* rootName,const char* buffer) {
+	theBuffer = buffer;
+	theBufferEnd = buffer + strlen(buffer) - 1;
+	return Namespace_loadXml(ns,nsid,rootName,readFromTheBuffer);
+}
 
 // FIXME: most of the following code should be generated as a template from the ns0-defining xml-files
 /** @brief sam (abbr. for server_application_memory) is a flattened memory structure of the UAVariables in ns0 */
@@ -36,43 +117,32 @@ void sam_attach(Namespace *ns,UA_UInt32 ns0id,UA_Int32 type, void* p) {
 		if (result->nodeId.identifier.numeric == ns0id) {
 			if (result->nodeClass == UA_NODECLASS_VARIABLE) {
 				UA_VariableNode* variable = (UA_VariableNode*) result;
-				if (variable->dataType.identifier.numeric == UA_[type].ns0Id) {
+				if (variable->dataType.identifier.numeric == UA_.types[type].typeId.identifier.numeric) {
 					variable->value.arrayLength = 1;
-					if (variable->value.data == UA_NULL) {
-						UA_alloc((void**)&(variable->value.data), sizeof(void*));
-						variable->value.data[0] = UA_NULL;
-					}
-					if (UA_NodeId_isBuiltinType(&variable->dataType)) {
-						variable->value.data[0] = p;
-					} else {
-						if (variable->value.vt->ns0Id != UA_EXTENSIONOBJECT_NS0) {
-							printf("nodeId for id=%d, type=%d\n should be an extension object", ns0id, type);
-						} else {
-							if (variable->value.data[0] == UA_NULL) {
-								UA_alloc((void**)&(variable->value.data[0]), sizeof(UA_ExtensionObject));
-							}
-							UA_ExtensionObject* eo = (UA_ExtensionObject*) variable->value.data[0];
-							eo->typeId = variable->dataType;
-							eo->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
-							// FIXME: This code is valid for ns0 and numeric identifiers only
-							eo->body.length = UA_[UA_ns0ToVTableIndex(variable->dataType.identifier.numeric)].memSize;
-							eo->body.data = p;
-						}
-					}
+					variable->value.data = p;
 				} else {
-					printf("wrong datatype for id=%d, expected=%d, retrieved=%d\n", ns0id, UA_[type].ns0Id, variable->dataType.identifier.numeric);
+					UA_alloc((void**)&variable->value.data, sizeof(UA_ExtensionObject));
+					UA_ExtensionObject* eo = (UA_ExtensionObject*) variable->value.data;
+					eo->typeId = variable->dataType;
+					eo->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
+					// FIXME: This code is valid for ns0 and numeric identifiers only
+					eo->body.length = UA_.types[UA_ns0ToVTableIndex(&variable->dataType)].memSize;
+					eo->body.data = p;
 				}
-			} else {
-				perror("Namespace_getWritable returned wrong node class");
 			}
-		} else {
-			printf("retrieving node={i=%d} returned node={i=%d}\n", ns0id, result->nodeId.identifier.numeric);
 		}
-		Namespace_Entry_Lock_release(lock);
-	} else {
-		printf("retrieving node={i=%d} returned error code %d\n",ns0id,retval);
 	}
 }
+	/* 	} else { */
+	/* 		perror("Namespace_getWritable returned wrong node class"); */
+	/* 	} */
+	/* } else { */
+	/* 	printf("retrieving node={i=%d} returned node={i=%d}\n", ns0id, result->nodeId.identifier.numeric); */
+	/* } */
+	/*        Namespace_Entry_Lock_release(lock); */
+	/* 	} else { */
+	/* 	printf("retrieving node={i=%d} returned error code %d\n",ns0id,retval); */
+	/* } */
 
 void sam_init(Namespace* ns) {
 	// Initialize the strings
@@ -108,7 +178,7 @@ UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const *
 		return UA_ERR_INVALID_VALUE;
 	UA_Int32 i, n;
 	for (i = 0, n = 0; i < node->referencesSize; i++ ) {
-		if (node->references[i]->referenceTypeId.identifier.numeric == 47 && node->references[i]->isInverse != UA_TRUE) {
+		if (node->references[i].referenceTypeId.identifier.numeric == 47 && node->references[i].isInverse != UA_TRUE) {
 			n++;
 		}
 	}
@@ -125,10 +195,10 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 
 	UA_Int32 i, n;
 	for (i = 0, n = 0; i < node->referencesSize; i++ ) {
-		if (node->references[i]->referenceTypeId.identifier.numeric == 47 && node->references[i]->isInverse != UA_TRUE) {
+		if (node->references[i].referenceTypeId.identifier.numeric == 47 && node->references[i].isInverse != UA_TRUE) {
 			n++;
 			if (n == idx) {
-				*result = &(node->references[i]->targetId.nodeId);
+				*result = &(node->references[i].targetId.nodeId);
 				return retval;
 			}
 		}
@@ -137,34 +207,34 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 }
 
 
-UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const * id, UA_Int32* pos, UA_ByteString *dst) {
+UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const * id, UA_ByteString *dst, UA_UInt32* offset) {
 	UA_Int32 i, retval = UA_SUCCESS;
 	if (UA_NodeId_isBasicType(id)) {
 		UA_Node const * result;
 		Namespace_Entry_Lock* lock;
 		if ((retval = Namespace_get(ns,id,&result,&lock)) == UA_SUCCESS)
-			UA_Variant_encodeBinary(&((UA_VariableNode *) result)->value,pos,dst);
+			UA_Variant_encodeBinary(&((UA_VariableNode *) result)->value,dst,offset);
 	} else {
 		UA_Int32 nComp = 0;
 		if ((retval = Namespace_getNumberOfComponents(ns,id,&nComp)) == UA_SUCCESS) {
 			for (i=0; i < nComp; i++) {
 				UA_NodeId* comp = UA_NULL;
 				Namespace_getComponent(ns,id,i,&comp);
-				UAX_NodeId_encodeBinaryByMetaData(ns,comp, pos, dst);
+				UAX_NodeId_encodeBinaryByMetaData(ns,comp, dst, offset);
 			}
 		}
 	}
 	return retval;
 }
 
-UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_Int32* pos, UA_ByteString *dst) {
+UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_ByteString *dst, UA_UInt32* offset) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
 	Namespace_Entry_Lock* lock;
 
 	if ((retval = Namespace_get(ns,id,&node,&lock)) == UA_SUCCESS) {
 		if (node->nodeClass == UA_NODECLASS_VARIABLE) {
-			retval = UA_Variant_encodeBinary(&((UA_VariableNode*) node)->value,pos,dst);
+			retval = UA_Variant_encodeBinary(&((UA_VariableNode*) node)->value,dst,offset);
 		}
 		Namespace_Entry_Lock_release(lock);
 	}
@@ -183,7 +253,7 @@ int main() {
 	// encoding buffer
 	char buf[1024];
 	UA_ByteString buffer = { 1024, (UA_Byte*) buf };
-	UA_Int32 pos = 0;
+	UA_UInt32 pos = 0;
 
 	UA_NodeId nodeid;
 	nodeid.encodingByte = UA_NODEIDTYPE_FOURBYTE;
@@ -197,7 +267,7 @@ int main() {
 	for (i=0;i<1E5 && retval == UA_SUCCESS;i++) {
 		pos = 0;
 		sam.serverStatus.currentTime = UA_DateTime_now();
-		retval |= UAX_NodeId_encodeBinary(ns,&nodeid,&pos,&buffer);
+		retval |= UAX_NodeId_encodeBinary(ns,&nodeid,&buffer,&pos);
 	}
 	UA_DateTime tEnd = UA_DateTime_now();
 	// tStart, tEnd count in 100 ns steps, so 10 steps = 1 µs

+ 0 - 8
include/Makefile.am

@@ -1,8 +0,0 @@
-TOOL_DIR = ../tools
-
-all-local: opcua.h ua_namespace_0.h
-
-opcua.h: $(TOOL_DIR)/opcua.hgen
-	cp $< $@
-ua_namespace_0.h: $(TOOL_DIR)/ua_namespace_0.hgen
-	cp $< $@

+ 0 - 490
include/ua_basictypes.h

@@ -1,490 +0,0 @@
-#ifndef OPCUA_BASICTYPES_H_
-#define OPCUA_BASICTYPES_H_
-
-#include <stdint.h>
-
-#define DBG_VERBOSE(expression) // omit debug code
-#define DBG_ERR(expression) // omit debug code
-#define DBG(expression) // omit debug code
-#if defined(DEBUG) 		// --enable-debug=(yes|verbose)
-# undef DBG
-# define DBG(expression) expression
-# undef DBG_ERR
-# define DBG_ERR(expression) expression
-# if defined(VERBOSE) 	// --enable-debug=verbose
-#  undef DBG_VERBOSE
-#  define DBG_VERBOSE(expression) expression
-# endif
-#endif
-
-/* Basic types */
-typedef _Bool UA_Boolean;
-typedef uint8_t UA_Byte;
-typedef int8_t UA_SByte;
-typedef int16_t UA_Int16;
-typedef uint16_t UA_UInt16;
-typedef int32_t UA_Int32;
-typedef uint32_t UA_UInt32;
-typedef int64_t UA_Int64;
-typedef uint64_t UA_UInt64;
-typedef float UA_Float;
-typedef double UA_Double;
-
-/* ByteString - Part: 6, Chapter: 5.2.2.7, Page: 17 */
-typedef struct UA_ByteString {
-	UA_Int32 	length;
-	UA_Byte*	data;
-} UA_ByteString;
-
-/* Function return values */
-#define UA_SUCCESS 0
-#define UA_NO_ERROR UA_SUCCESS
-#define UA_ERROR (0x01 << 31)
-#define UA_ERR_INCONSISTENT  (UA_ERROR | (0x01 << 1))
-#define UA_ERR_INVALID_VALUE (UA_ERROR | (0x01 << 2))
-#define UA_ERR_NO_MEMORY     (UA_ERROR | (0x01 << 3))
-#define UA_ERR_NOT_IMPLEMENTED (UA_ERROR | (0x01 << 4))
-
-/* Boolean values and null */
-#define UA_TRUE (42==42)
-#define TRUE UA_TRUE
-#define UA_FALSE (!UA_TRUE)
-#define FALSE UA_FALSE
-
-/* Compare values */
-#define UA_EQUAL 0
-#define UA_NOT_EQUAL (!UA_EQUAL)
-
-/* heap memory functions */
-#define UA_NULL ((void*)0)
-extern void const * UA_alloc_lastptr;
-#define UA_free(ptr) _UA_free(ptr,#ptr,__FILE__,__LINE__)
-UA_Int32 _UA_free(void * ptr,char*,char*,int);
-UA_Int32 UA_memcpy(void *dst, void const *src, int size);
-#define UA_alloc(ptr,size) _UA_alloc(ptr,size,#ptr,#size,__FILE__,__LINE__)
-UA_Int32 _UA_alloc(void ** dst, int size,char*,char*,char*,int);
-
-/* Stop decoding at the first failure. Free members that were already allocated.
-   It is assumed that retval is already defined. */
-#define CHECKED_DECODE(DECODE, CLEAN_UP) do { \
-	retval |= DECODE; \
-	if(retval != UA_SUCCESS) { \
-		CLEAN_UP; \
-		return retval; \
-	} } while(0) \
-
-/* Array operations */
-UA_Int32 UA_Array_calcSize(UA_Int32 noElements, UA_Int32 type, void const * const * ptr);
-UA_Int32 UA_Array_encodeBinary(void const * const *src, UA_Int32 noElements, UA_Int32 type, UA_Int32* pos, UA_ByteString * dst);
-UA_Int32 UA_Array_decodeBinary(UA_ByteString const * src,UA_Int32 noElements, UA_Int32 type, UA_Int32* pos, void *** dst);
-UA_Int32 UA_Array_delete(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_new(void ***p,UA_Int32 noElements, UA_Int32 type);
-UA_Int32 UA_Array_copy(void const * const *src,UA_Int32 noElements, UA_Int32 type, void ***dst);
-
-/* XML prelimiaries */
-struct XML_Stack;
-typedef char const * const XML_Attr;
-typedef char const * cstring;
-#define XML_STACK_MAX_DEPTH 10
-#define XML_STACK_MAX_CHILDREN 40
-typedef UA_Int32 (*XML_decoder)(struct XML_Stack* s, XML_Attr* attr, void* dst, UA_Boolean isStart);
-
-#define UA_TYPE_METHOD_PROTOTYPES(TYPE) \
-	UA_Int32 TYPE##_calcSize(TYPE const * ptr);							\
-	UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_Int32* pos, UA_ByteString * dst);	\
-	UA_Int32 TYPE##_decodeBinary(UA_ByteString const * src, UA_Int32* pos, TYPE * dst);	\
-	UA_Int32 TYPE##_decodeXML(struct XML_Stack* s, XML_Attr* attr, TYPE* dst, UA_Boolean isStart); \
-	UA_Int32 TYPE##_delete(TYPE * p);									\
-	UA_Int32 TYPE##_deleteMembers(TYPE * p);							\
-	UA_Int32 TYPE##_init(TYPE * p);										\
-	UA_Int32 TYPE##_new(TYPE ** p); 									\
-	UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
-
-#define UA_TYPE_METHOD_CALCSIZE_SIZEOF(TYPE) \
-UA_Int32 TYPE##_calcSize(TYPE const * p) { return sizeof(TYPE); }
-
-#define UA_TYPE_METHOD_CALCSIZE_AS(TYPE, TYPE_AS) \
-UA_Int32 TYPE##_calcSize(TYPE const * p) { return TYPE_AS##_calcSize((TYPE_AS*) p); }
-
-#define UA_TYPE_METHOD_DELETE_FREE(TYPE) \
-UA_Int32 TYPE##_delete(TYPE * p) { return UA_free(p); }
-
-#define UA_TYPE_METHOD_DELETE_AS(TYPE, TYPE_AS) \
-UA_Int32 TYPE##_delete(TYPE * p) { return TYPE_AS##_delete((TYPE_AS*) p);}
-
-#define UA_TYPE_METHOD_DELETE_STRUCT(TYPE) \
-UA_Int32 TYPE##_delete(TYPE *p) { \
-	UA_Int32 retval = UA_SUCCESS; \
-	retval |= TYPE##_deleteMembers(p); \
-	retval |= UA_free(p); \
-	return retval; \
-}
-
-#define UA_TYPE_METHOD_COPY(TYPE) \
-UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) { \
-	UA_Int32 retval = UA_SUCCESS; \
-	retval |= UA_memcpy(dst, src, TYPE##_calcSize(UA_NULL)); \
-	return retval; \
-}
-
-#define UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(TYPE) \
-UA_Int32 TYPE##_deleteMembers(TYPE * p) { return UA_SUCCESS; }
-
-#define UA_TYPE_METHOD_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-UA_Int32 TYPE##_deleteMembers(TYPE * p) { return TYPE_AS##_deleteMembers((TYPE_AS*) p);}
-
-#define UA_TYPE_METHOD_DECODEBINARY_AS(TYPE,TYPE_AS) \
-UA_Int32 TYPE##_decodeBinary(UA_ByteString const * src, UA_Int32* pos, TYPE *dst) { \
-	return TYPE_AS##_decodeBinary(src,pos,(TYPE_AS*) dst); \
-}
-
-#define UA_TYPE_METHOD_DECODEXML_NOTIMPL(TYPE) \
-	UA_Int32 TYPE##_decodeXML(XML_Stack* s, XML_Attr* attr, TYPE* dst, _Bool isStart) { \
-		DBG_VERBOSE(printf(#TYPE "_decodeXML entered with dst=%p,isStart=%d\n", (void* ) dst, isStart)); \
-		return UA_ERR_NOT_IMPLEMENTED;\
-	}
-
-#define UA_TYPE_METHOD_DECODEXML_AS(TYPE,TYPE_AS) \
-	UA_Int32 TYPE##_decodeXML(struct XML_Stack* s, XML_Attr* attr, TYPE* dst, _Bool isStart) { \
-		return TYPE_AS##_decodeXML(s,attr,(TYPE_AS*) dst,isStart); \
-	}
-
-#define UA_TYPE_METHOD_ENCODEBINARY_AS(TYPE,TYPE_AS) \
-UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_Int32* pos, UA_ByteString *dst) { \
-	return TYPE_AS##_encodeBinary((TYPE_AS*) src,pos,dst); \
-}
-
-#define UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS) \
-UA_Int32 TYPE##_init(TYPE * p) { \
-	return TYPE_AS##_init((TYPE_AS*)p); \
-}
-#define UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS) \
-UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {return TYPE_AS##_copy((TYPE_AS*) src,(TYPE_AS*)dst); \
-}
-
-#define UA_TYPE_METHOD_PROTOTYPES_AS_WOXML(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_CALCSIZE_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_ENCODEBINARY_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_DECODEBINARY_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_DELETE_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS)
-
-#define UA_TYPE_METHOD_PROTOTYPES_AS(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_PROTOTYPES_AS_WOXML(TYPE, TYPE_AS) \
-	UA_TYPE_METHOD_DECODEXML_AS(TYPE, TYPE_AS)
-
-#define UA_TYPE_METHOD_NEW_DEFAULT(TYPE) \
-UA_Int32 TYPE##_new(TYPE ** p) { \
-	UA_Int32 retval = UA_SUCCESS;\
-	retval |= UA_alloc((void**)p, TYPE##_calcSize(UA_NULL));\
-	retval |= TYPE##_init(*p);\
-	return retval;\
-}
-
-#define UA_TYPE_METHOD_INIT_DEFAULT(TYPE) \
-UA_Int32 TYPE##_init(TYPE * p) { \
-	if(p==UA_NULL)return UA_ERROR;\
-	*p = (TYPE)0;\
-	return UA_SUCCESS;\
-}
-//#define UA_TYPE_COPY_METHOD_PROTOTYPE(TYPE) \  UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
-
-/*** Prototypes for basic types **/
-UA_TYPE_METHOD_PROTOTYPES (UA_Boolean)
-UA_TYPE_METHOD_PROTOTYPES (UA_Byte)
-UA_TYPE_METHOD_PROTOTYPES (UA_SByte)
-UA_TYPE_METHOD_PROTOTYPES (UA_Int16)
-UA_TYPE_METHOD_PROTOTYPES (UA_UInt16)
-UA_TYPE_METHOD_PROTOTYPES (UA_Int32)
-UA_TYPE_METHOD_PROTOTYPES (UA_UInt32)
-UA_TYPE_METHOD_PROTOTYPES (UA_Int64)
-UA_TYPE_METHOD_PROTOTYPES (UA_UInt64)
-UA_TYPE_METHOD_PROTOTYPES (UA_Float)
-UA_TYPE_METHOD_PROTOTYPES (UA_Double)
-
-/**
-* StatusCodeBinaryEncoding
-* Part: 6
-* Chapter: 5.2.2.11
-* Page: 20
-* 
-* StatusCodes aren't an enum (=int), since 32 unsigned bits are needed.
-* See also ua_statuscodes.h
-*/
-typedef UA_UInt32 UA_StatusCode;
-UA_TYPE_METHOD_PROTOTYPES (UA_StatusCode)
-
-/** IntegerId - Part: 4, Chapter: 7.13, Page: 118 */
-typedef float UA_IntegerId;
-UA_TYPE_METHOD_PROTOTYPES (UA_IntegerId)
-
-/** @brief String Object
- *
- *  String - Part: 6, Chapter: 5.2.2.4, Page: 16
- */
-typedef struct UA_String {
-	UA_Int32 	length;
-	UA_Byte*	data;
-} UA_String;
-UA_TYPE_METHOD_PROTOTYPES (UA_String)
-//UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
-UA_Int32 UA_String_copycstring(char const * src, UA_String* dst);
-UA_Int32 UA_String_copyprintf(char const * fmt, UA_String* dst, ...);
-UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2);
-void UA_String_printf(char const * label, const UA_String* string);
-void UA_String_printx(char const * label, const UA_String* string);
-void UA_String_printx_hex(char const * label, const UA_String* string);
-
-/* ByteString - Part: 6, Chapter: 5.2.2.7, Page: 17 */
-UA_TYPE_METHOD_PROTOTYPES (UA_ByteString)
-UA_Int32 UA_ByteString_compare(const UA_ByteString *string1, const UA_ByteString *string2);
-//UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
-UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length);
-extern UA_ByteString UA_ByteString_securityPoliceNone;
-
-/* LocalizedTextBinaryEncoding - Part: 6, Chapter: 5.2.2.14, Page: 21 */
-enum UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_enum {
-	UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE = 0x01,
-	UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT = 0x02
-};
-
-typedef struct UA_LocalizedText {
-	UA_Byte encodingMask;
-	UA_String locale;
-	UA_String text;
-} UA_LocalizedText;
-UA_TYPE_METHOD_PROTOTYPES (UA_LocalizedText)
-
-UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst);
-void UA_ByteString_printf(char* label, const UA_ByteString* string);
-void UA_ByteString_printx(char* label, const UA_ByteString* string);
-void UA_ByteString_printx_hex(char* label, const UA_ByteString* string);
-
-/* GuidType - Part: 6, Chapter: 5.2.2.6 Page: 17 */
-typedef struct UA_Guid {
-	UA_UInt32 data1;
-	UA_UInt16 data2;
-	UA_UInt16 data3;
-	UA_Byte data4[8];
-} UA_Guid;
-UA_TYPE_METHOD_PROTOTYPES (UA_Guid)
-UA_Int32 UA_Guid_compare(const UA_Guid *g1, const UA_Guid *g2);
-
-/* DateTime - Part: 6, Chapter: 5.2.2.5, Page: 16 */
-typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
-UA_TYPE_METHOD_PROTOTYPES (UA_DateTime)
-
-UA_DateTime UA_DateTime_now();
-typedef struct UA_DateTimeStruct {
-	UA_Int16 nanoSec;
-	UA_Int16 microSec;
-	UA_Int16 milliSec;
-	UA_Int16 sec;
-	UA_Int16 min;
-	UA_Int16 hour;
-	UA_Int16 day;
-	UA_Int16 mounth;
-	UA_Int16 year;
-} UA_DateTimeStruct;
-UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time);
-UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String* timeString);
-
-typedef struct UA_NodeId {
-	UA_Byte   encodingByte; //enum BID_NodeIdEncodingValuesType
-	UA_UInt16 namespace;
-    union {
-        UA_UInt32 numeric;
-        UA_String string;
-        UA_Guid guid;
-        UA_ByteString byteString;
-    } identifier;
-} UA_NodeId;
-UA_TYPE_METHOD_PROTOTYPES (UA_NodeId)
-
-UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2);
-void UA_NodeId_printf(char* label, const UA_NodeId* node);
-UA_Boolean UA_NodeId_isNull(const UA_NodeId* p);
-UA_Int16 UA_NodeId_getNamespace(UA_NodeId const * id);
-UA_Int16 UA_NodeId_getIdentifier(UA_NodeId const * id);
-_Bool UA_NodeId_isBasicType(UA_NodeId const * id);
-
-
-/* XmlElement - Part: 6, Chapter: 5.2.2.8, Page: 17 */
-typedef struct UA_XmlElement {
-	//TODO Überlegung ob man es direkt als ByteString speichert oder als String
-	UA_ByteString data;
-} UA_XmlElement;
-UA_TYPE_METHOD_PROTOTYPES (UA_XmlElement)
-
-/* ExpandedNodeId - Part: 6, Chapter: 5.2.2.10, Page: 19 */
-// 62541-6 Chapter 5.2.2.9, Table 5
-#define UA_NODEIDTYPE_NAMESPACE_URI_FLAG 0x80
-#define UA_NODEIDTYPE_SERVERINDEX_FLAG   0x40
-#define UA_NODEIDTYPE_MASK (~(UA_NODEIDTYPE_NAMESPACE_URI_FLAG | UA_NODEIDTYPE_SERVERINDEX_FLAG))
-typedef struct UA_ExpandedNodeId {
-	UA_NodeId nodeId;
-	UA_String namespaceUri;
-	UA_UInt32 serverIndex;
-} UA_ExpandedNodeId;
-UA_TYPE_METHOD_PROTOTYPES(UA_ExpandedNodeId)
-UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId* p);
-
-/* IdentifierType */
-typedef UA_Int32 UA_IdentifierType;
-UA_TYPE_METHOD_PROTOTYPES(UA_IdentifierType)
-
-/* ExtensionObjectBinaryEncoding - Part: 6, Chapter: 5.2.2.15, Page: 21 */
-typedef struct UA_ExtensionObject {
-	UA_NodeId typeId;
-	UA_Byte encoding; //Type of the enum UA_ExtensionObjectEncodingMaskType
-	UA_ByteString body; // contains either the bytestring or a pointer to the memory-object
-} UA_ExtensionObject;
-UA_TYPE_METHOD_PROTOTYPES(UA_ExtensionObject)
-
-enum UA_ExtensionObject_EncodingMaskType_enum {
-	UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED =   0x00,
-	UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING = 	0x01,
-	UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML =         0x02
-};
-
-/* QualifiedNameBinaryEncoding - Part: 6, Chapter: 5.2.2.13, Page: 20 */
-typedef struct UA_QualifiedName {
-	UA_UInt16 namespaceIndex;
-	/*UA_UInt16 reserved; removed by Sten since unclear origin*/
-	UA_String name;
-} UA_QualifiedName;
-UA_TYPE_METHOD_PROTOTYPES(UA_QualifiedName)
-
-/* XML Decoding */
-
-/** @brief A readable shortcut for NodeIds. A list of aliases is intensively used in the namespace0-xml-files */
-typedef struct UA_NodeSetAlias {
-	UA_String alias;
-	UA_String value;
-} UA_NodeSetAlias;
-UA_TYPE_METHOD_PROTOTYPES (UA_NodeSetAlias)
-
-/** @brief UA_NodeSetAliases - a list of aliases */
-typedef struct UA_NodeSetAliases {
-	UA_Int32 size;
-	UA_NodeSetAlias** aliases;
-} UA_NodeSetAliases;
-UA_TYPE_METHOD_PROTOTYPES (UA_NodeSetAliases)
-
-typedef struct XML_child {
-	cstring name;
-	UA_Int32 length;
-	UA_Int32 type;
-	XML_decoder elementHandler;
-	void* obj;
-} XML_child;
-
-typedef struct XML_Parent {
-	cstring name;
-	int textAttribIdx; // -1 - not set
-	cstring textAttrib;
-	int activeChild; // -1 - no active child
-	int len; // -1 - empty set
-	XML_child children[XML_STACK_MAX_CHILDREN];
-} XML_Parent;
-
-typedef struct XML_Stack {
-	int depth;
-	XML_Parent parent[XML_STACK_MAX_DEPTH];
-	UA_NodeSetAliases* aliases; // shall point to the aliases of the NodeSet after reading
-} XML_Stack;
-
-typedef struct UA_VTable {
-	UA_UInt32 ns0Id;
-	UA_Int32 (*calcSize)(void const * ptr);
-	UA_Int32 (*decodeBinary)(UA_ByteString const * src, UA_Int32* pos, void* dst);
-	UA_Int32 (*encodeBinary)(void const * src, UA_Int32* pos, UA_ByteString* dst);
-	UA_Int32 (*decodeXML)(XML_Stack* s, XML_Attr* attr, void* dst, UA_Boolean isStart);
-	UA_Int32 (*init)(void * p);
-	UA_Int32 (*new)(void ** p);
-	UA_Int32 (*copy)(void const *src,void *dst);
-	UA_Int32 (*delete)(void * p);
-	UA_UInt32 memSize; // size of the struct only in memory (no dynamic components)
-	UA_Byte* name;
-} UA_VTable;
-
-/* VariantBinaryEncoding - Part: 6, Chapter: 5.2.2.16, Page: 22 */
-enum UA_VARIANT_ENCODINGMASKTYPE_enum {
-	UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F,	// bits 0:5
-	UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS =  (0x01 << 6), // bit 6
-	UA_VARIANT_ENCODINGMASKTYPE_ARRAY =       (0x01 << 7) // bit 7
-};
-
-typedef struct UA_Variant {
-	UA_VTable* vt;		// internal entry into vTable
-	UA_Byte encodingMask; 	// Type of UA_Variant_EncodingMaskType_enum
-	UA_Int32 arrayLength;	// total number of elements
-	UA_Int32 arrayDimensionsLength;
-	UA_Int32 **arrayDimensions;
-	void** data;
-} UA_Variant;
-UA_TYPE_METHOD_PROTOTYPES (UA_Variant)
-
-UA_Int32 UA_Variant_copySetValue(UA_Variant *v, UA_Int32 type, const void* data);
-UA_Int32 UA_Variant_copySetArray(UA_Variant *v, UA_Int32 type_id, UA_Int32 arrayLength, UA_UInt32 elementSize, const void* array);
-
-/**
-   @brief Functions UA_Variant_borrowSetValue and ..Array allow to define
- variants whose payload will not be deleted. This is achieved by a second
- vtable. The functionality can be used e.g. when UA_VariableNodes point into a
- "father" structured object that is stored in an UA_VariableNode itself. */
-UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type, const void* data); // Take care not to free the data before the variant.
-UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_Int32 type, UA_Int32 arrayLength, const void* data); // Take care not to free the data before the variant.
-
-/* DataValue - Part: 6, Chapter: 5.2.2.17, Page: 23 */
-typedef struct UA_DataValue {
-	UA_Byte encodingMask;
-	UA_Variant value;
-	UA_StatusCode status;
-	UA_DateTime sourceTimestamp;
-	UA_Int16 sourcePicoseconds;
-	UA_DateTime serverTimestamp;
-	UA_Int16 serverPicoseconds;
-} UA_DataValue;
-UA_TYPE_METHOD_PROTOTYPES(UA_DataValue)
-
-/** 62541-6, §5.2.2.17, Table 15 */
-enum UA_DATAVALUE_ENCODINGMASKTYPE_enum {
-	UA_DATAVALUE_ENCODINGMASK_VARIANT = 	        0x01,
-	UA_DATAVALUE_ENCODINGMASK_STATUSCODE = 	        0x02,
-	UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP = 	0x04,
-	UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP = 	0x08,
-	UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS = 	0x10,
-	UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS = 	0x20
-};
-
-/* DiagnosticInfo - Part: 6, Chapter: 5.2.2.12, Page: 20 */
-typedef struct UA_DiagnosticInfo {
-	UA_Byte encodingMask; //Type of the Enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE
-	UA_Int32 symbolicId;
-	UA_Int32 namespaceUri;
-	UA_Int32 localizedText;
-	UA_Int32 locale;
-	UA_String additionalInfo;
-	UA_StatusCode innerStatusCode;
-	struct UA_DiagnosticInfo* innerDiagnosticInfo;
-} UA_DiagnosticInfo;
-UA_TYPE_METHOD_PROTOTYPES(UA_DiagnosticInfo)
-
-enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
-	UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID = 		 0x01,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE = 		     0x02,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT = 	     0x04,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE = 			 0x08,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO =      0x10,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE =     0x20,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
-};
-
-typedef void UA_InvalidType;
-UA_TYPE_METHOD_PROTOTYPES (UA_InvalidType)
-
-#endif /* OPCUA_BASICTYPES_H_ */

tools/NodeIds.csv → schema/NodeIds.csv


examples/src/Opc.Ua.NodeSet2.Part3.xml → schema/Opc.Ua.NodeSet2.Part3.xml


examples/src/Opc.Ua.NodeSet2.Part4.xml → schema/Opc.Ua.NodeSet2.Part4.xml


examples/src/Opc.Ua.NodeSet2.Part5.xml → schema/Opc.Ua.NodeSet2.Part5.xml


examples/src/Opc.Ua.NodeSet2.xml → schema/Opc.Ua.NodeSet2.xml


tools/Opc.Ua.Types.bsd → schema/Opc.Ua.Types.bsd


tools/UA_stackInternalTypes.bsd → schema/UA_stackInternalTypes.bsd


+ 15 - 5
src/Makefile.am

@@ -1,9 +1,13 @@
-AM_CFLAGS = $(GLOBAL_AM_CFLAGS) -I$(top_builddir)/include -I$(top_builddir)/src -I. -I$(top_builddir)/src/util
+AM_CFLAGS = $(GLOBAL_AM_CFLAGS) -I$(top_builddir)/src -I. -I$(top_builddir)/src/util
 TOOL_DIR = ../tools
+SCHEMA_DIR = ../schema
 lib_LTLIBRARIES = libopen62541.la
+lib_LTLIBRARIES: generate_types generate_namespace_0
 libopen62541_la_LDFLAGS = -avoid-version -no-undefined
-libopen62541_la_SOURCES = opcua.c \
-						  ua_basictypes.c \
+libopen62541_la_SOURCES = ua_types.c \
+						  ua_types_generated.c \
+						  ua_types_encoding_binary.c \
+						  ua_types_encoding_xml.c \
 						  ua_namespace_0.c \
 						  util/ua_list.c \
 						  util/ua_indexedList.c \
@@ -20,9 +24,15 @@ libopen62541_la_SOURCES = opcua.c \
 						  ua_application.c \
 						  ua_xml.c
 
-.PHONY: convenience-link clean-convenience-link
+generate_types: $(SCHEMA_DIR)/Opc.Ua.Types.bsd $(TOOL_DIR)/generate_builtin.py
+	python $(TOOL_DIR)/generate_builtin.py $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated
 
-convenience-link: $(lib_LTLIBRARIES)
+generate_namespace_0: $(SCHEMA_DIR)/NodeIds.csv $(TOOL_DIR)/generate_namespace.py
+	python $(TOOL_DIR)/generate_namespace.py $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0
+
+.PHONY: convenience-link clean-convenience-link generate_types generate_namespace_0
+
+convenience-link: $(lib_LTLIBRARIES) 
 	@test -e $(top_builddir)/lib || mkdir $(top_builddir)/lib
 	@for soname in `echo | $(EGREP) "^dlname=" $^ | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do  \
 		echo "$$soname: creating convenience link from $(abs_builddir)/.libs to $(top_builddir)/lib"; \

+ 3 - 3
src/ua_application.c

@@ -11,7 +11,7 @@ Application appMockup = {
 };
 
 UA_Node* create_node_ns0(UA_Int32 class, UA_Int32 nodeClass, UA_Int32 const id, char const * qn, char const * dn, char const * desc) {
-	UA_Node* n; UA_[class].new((void **)&n);
+	UA_Node* n; UA_.types[class].new((void **)&n);
 	n->nodeId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
 	n->nodeId.namespace = 0;
 	n->nodeId.identifier.numeric = id;
@@ -47,8 +47,8 @@ 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);
-	v->value.vt = &UA_[UA_STRING];
+	UA_Array_new((void**)&v->value.data, 2, 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]);

+ 1 - 1
src/ua_application.h

@@ -1,7 +1,7 @@
 #ifndef OPCUA_APPLICATION_H_
 #define OPCUA_APPLICATION_H_
 
-#include "opcua.h"
+#include "ua_types.h"
 #include "ua_namespace.h"
 #include "ua_indexedList.h"
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 1691
src/ua_basictypes.c


+ 1 - 1
include/ua_indexedList.h

@@ -1,7 +1,7 @@
 #ifndef UA_INDEXEDLIST_H_
 #define UA_INDEXEDLIST_H_
 
-#include "opcua.h"
+#include "ua_types.h"
 /* UA_indexedList reuses many types of UA_list */
 #include "ua_list.h"
 

+ 1 - 1
include/ua_list.h

@@ -1,9 +1,9 @@
 #ifndef UA_LIST_H_
 #define UA_LIST_H_
 
-#include "opcua.h"
 #include <stddef.h> /* Needed for sys/queue.h */
 #include <sys/queue.h>
+#include "ua_types.h"
 
 
 /**********************/

+ 2 - 2
src/ua_namespace.h

@@ -1,8 +1,8 @@
 #ifndef __NAMESPACE_H__
 #define __NAMESPACE_H__
 
-#include "ua_basictypes.h"
-#include "opcua.h"
+#include "ua_types.h"
+#include "ua_types_generated.h"
 #include "ua_list.h"
 
 #ifdef MULTITHREADING

+ 1 - 1
src/ua_services.h

@@ -7,7 +7,7 @@
 #ifndef UA_SERVICES_H_
 #define UA_SERVICES_H_
 
-#include "opcua.h"
+#include "ua_types.h"
 #include "ua_application.h"
 #include "ua_transport_binary_secure.h"
 

+ 59 - 59
src/ua_services_attribute.c

@@ -28,23 +28,23 @@ enum UA_AttributeId {
 
 #define CHECK_NODECLASS(CLASS) do {									\
 		if((node->nodeClass & (CLASS)) != 0x00) {					\
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;		\
-			v->status = UA_STATUSCODE_BADNOTREADABLE;				\
+			v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;	\
+			v.status = UA_STATUSCODE_BADNOTREADABLE;				\
 		}															\
 		break;														\
 	} while(0)
 
-static UA_DataValue *service_read_node(Application * app, const UA_ReadValueId * id) {
-	UA_DataValue *v;
-	UA_DataValue_new(&v);
+static UA_DataValue service_read_node(Application * app, const UA_ReadValueId * id) {
+	UA_DataValue v;
+	UA_DataValue_init(&v);
 
 	DBG(printf("service_read_node - entered with ns=%d,id=%d,attr=%i\n", id->nodeId.namespace, id->nodeId.identifier.numeric, id->attributeId));
 	Namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespace);
 
 	if(ns == UA_NULL) {
 		DBG_VERBOSE(printf("service_read_node - unknown namespace %d\n", id->nodeId.namespace));
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+		v.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
 		return v;
 	}
 	DBG_VERBOSE(UA_String_printf(",namespaceUri=", &(ns->namespaceUri)));
@@ -55,8 +55,8 @@ static UA_DataValue *service_read_node(Application * app, const UA_ReadValueId *
 	DBG_VERBOSE(UA_NodeId_printf("service_read_node - search for ", &(id->nodeId)));
 	UA_Int32 result = Namespace_get(ns, &(id->nodeId), &node, &lock);
 	if(result != UA_SUCCESS || node == UA_NULL) {
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+		v.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
 		return v;
 	}
 	DBG_VERBOSE(UA_NodeId_printf("service_read_node - found node=", &(node->nodeId)));
@@ -65,121 +65,121 @@ static UA_DataValue *service_read_node(Application * app, const UA_ReadValueId *
 
 	switch (id->attributeId) {
 	case UA_ATTRIBUTEID_NODEID:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_NODEID, &node->nodeId);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_NODEID, &node->nodeId);
 		break;
 	case UA_ATTRIBUTEID_NODECLASS:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_UINT32, &node->nodeClass);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_UINT32, &node->nodeClass);
 		break;
 	case UA_ATTRIBUTEID_BROWSENAME:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_QUALIFIEDNAME, &node->browseName);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_QUALIFIEDNAME, &node->browseName);
 		break;
 	case UA_ATTRIBUTEID_DISPLAYNAME:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_LOCALIZEDTEXT, &node->displayName);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_LOCALIZEDTEXT, &node->displayName);
 		break;
 	case UA_ATTRIBUTEID_DESCRIPTION:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v->status = UA_STATUSCODE_BADNOTREADABLE;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+		v.status = UA_STATUSCODE_BADNOTREADABLE;
 		break;
 	case UA_ATTRIBUTEID_WRITEMASK:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_UINT32, &node->writeMask);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_UINT32, &node->writeMask);
 		break;
 	case UA_ATTRIBUTEID_USERWRITEMASK:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_UINT32, &node->userWriteMask);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_UINT32, &node->userWriteMask);
 		break;
 	case UA_ATTRIBUTEID_ISABSTRACT:
 		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_ReferenceTypeNode *) node)->isAbstract);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_ReferenceTypeNode *) node)->isAbstract);
 		break;
 	case UA_ATTRIBUTEID_SYMMETRIC:
 		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_ReferenceTypeNode *) node)->symmetric);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_ReferenceTypeNode *) node)->symmetric);
 		break;
 	case UA_ATTRIBUTEID_INVERSENAME:
 		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_LOCALIZEDTEXT, &((UA_ReferenceTypeNode *) node)->inverseName);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_LOCALIZEDTEXT, &((UA_ReferenceTypeNode *) node)->inverseName);
 		break;
 	case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
 		CHECK_NODECLASS(UA_NODECLASS_VIEW);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_ViewNode *) node)->containsNoLoops);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_ViewNode *) node)->containsNoLoops);
 		break;
 	case UA_ATTRIBUTEID_EVENTNOTIFIER:
 		CHECK_NODECLASS(UA_NODECLASS_VIEW);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BYTE, &((UA_ViewNode *) node)->eventNotifier);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BYTE, &((UA_ViewNode *) node)->eventNotifier);
 		break;
 	case UA_ATTRIBUTEID_VALUE:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
 		// TODO: Ensure that the borrowed value is not freed prematurely (multithreading)
-		retval |= UA_Variant_borrowSetValue(&v->value, UA_VARIANT, &((UA_VariableNode *) node)->value);
+		retval |= UA_Variant_borrowSetValue(&v.value, UA_VARIANT, &((UA_VariableNode *) node)->value);
 		break;
 	case UA_ATTRIBUTEID_DATATYPE:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_NODEID, &((UA_VariableTypeNode *) node)->dataType);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_NODEID, &((UA_VariableTypeNode *) node)->dataType);
 		break;
 	case UA_ATTRIBUTEID_VALUERANK:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_INT32, &((UA_VariableTypeNode *) node)->valueRank);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_INT32, &((UA_VariableTypeNode *) node)->valueRank);
 		break;
 	case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		UA_Variant_copySetArray(&v->value, UA_UINT32, ((UA_VariableTypeNode *) node)->arrayDimensionsSize, sizeof(UA_UInt32),
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		UA_Variant_copySetArray(&v.value, UA_UINT32, ((UA_VariableTypeNode *) node)->arrayDimensionsSize, sizeof(UA_UInt32),
 								&((UA_VariableTypeNode *) node)->arrayDimensions);
 		break;
 	case UA_ATTRIBUTEID_ACCESSLEVEL:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BYTE, &((UA_VariableNode *) node)->accessLevel);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BYTE, &((UA_VariableNode *) node)->accessLevel);
 		break;
 	case UA_ATTRIBUTEID_USERACCESSLEVEL:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BYTE, &((UA_VariableNode *) node)->userAccessLevel);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BYTE, &((UA_VariableNode *) node)->userAccessLevel);
 		break;
 	case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_DOUBLE, &((UA_VariableNode *) node)->minimumSamplingInterval);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_DOUBLE, &((UA_VariableNode *) node)->minimumSamplingInterval);
 		break;
 	case UA_ATTRIBUTEID_HISTORIZING:
 		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_VariableNode *) node)->historizing);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_VariableNode *) node)->historizing);
 		break;
 	case UA_ATTRIBUTEID_EXECUTABLE:
 		CHECK_NODECLASS(UA_NODECLASS_METHOD);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_MethodNode *) node)->executable);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_MethodNode *) node)->executable);
 		break;
 	case UA_ATTRIBUTEID_USEREXECUTABLE:
 		CHECK_NODECLASS(UA_NODECLASS_METHOD);
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v->value, UA_BOOLEAN, &((UA_MethodNode *) node)->userExecutable);
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+		retval |= UA_Variant_copySetValue(&v.value, UA_BOOLEAN, &((UA_MethodNode *) node)->userExecutable);
 		break;
 	default:
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v->status = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+		v.status = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
 		break;
 	}
 
 	Namespace_Entry_Lock_release(lock);
 
 	if(retval != UA_SUCCESS) {
-		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v->status = UA_STATUSCODE_BADNOTREADABLE;
+		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+		v.status = UA_STATUSCODE_BADNOTREADABLE;
 	}
 
 	return v;
@@ -198,11 +198,11 @@ UA_Int32 Service_Read(SL_Channel * channel, const UA_ReadRequest * request, UA_R
 	}
 
 	response->resultsSize = readsize;
-	UA_alloc((void **)&response->results, sizeof(void *) * readsize);
+	UA_alloc((void **)&response->results, sizeof(UA_DataValue) * readsize);
 	for(int i = 0; i < readsize; i++) {
 		DBG_VERBOSE(printf("service_read - attributeId=%d\n", request->nodesToRead[i]->attributeId));
 		DBG_VERBOSE(UA_NodeId_printf("service_read - nodeId=", &(request->nodesToRead[i]->nodeId)));
-		response->results[i] = service_read_node(channel->session->application, request->nodesToRead[i]);
+		response->results[i] = service_read_node(channel->session->application, &request->nodesToRead[i]);
 	}
 	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
 	response->diagnosticInfosSize = -1;

+ 12 - 12
src/ua_services_discovery.c

@@ -3,32 +3,32 @@ 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_ENDPOINTDESCRIPTION);
 
 	//Security issues:
 	//The policy should be 'http://opcfoundation.org/UA/SecurityPolicy#None'
 	//FIXME String or ByteString
-	UA_String_copy((UA_String*)&channel->localAsymAlgSettings.securityPolicyUri,&response->endpoints[0]->securityPolicyUri);
+	UA_String_copy((UA_String *)&channel->localAsymAlgSettings.securityPolicyUri, &response->endpoints[0].securityPolicyUri);
 	//FIXME hard-coded code
-	response->endpoints[0]->securityMode = UA_MESSAGESECURITYMODE_NONE;
-	UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary", &response->endpoints[0]->transportProfileUri);
+	response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
+	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_UserTokenPolicy *token = response->endpoints[0]->userIdentityTokens[0];
+	response->endpoints[0].userIdentityTokensSize = 1;
+	UA_Array_new((void**) &response->endpoints[0].userIdentityTokens, response->endpoints[0].userIdentityTokensSize, 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;
 	token->issuerEndpointUrl = (UA_String) {-1, UA_NULL};
 	token->issuedTokenType = (UA_String) {-1, UA_NULL};
 	token->securityPolicyUri = (UA_String) {-1, UA_NULL};
 
-	UA_String_copy(&request->endpointUrl,&response->endpoints[0]->endpointUrl);
-	UA_String_copycstring("http://open62541.info/product/release",&(response->endpoints[0]->server.productUri));
+	UA_String_copy(&request->endpointUrl,&response->endpoints[0].endpointUrl);
+	UA_String_copycstring("http://open62541.info/product/release",&(response->endpoints[0].server.productUri));
 	// FIXME: This information should be provided by the application, preferably in the address space
-	UA_String_copycstring("http://open62541.info/applications/4711",&(response->endpoints[0]->server.applicationUri));
-	UA_LocalizedText_copycstring("The open62541 application",&(response->endpoints[0]->server.applicationName));
+	UA_String_copycstring("http://open62541.info/applications/4711",&(response->endpoints[0].server.applicationUri));
+	UA_LocalizedText_copycstring("The open62541 application",&(response->endpoints[0].server.applicationName));
 	// FIXME: This should be a feature of the application and an enum
-	response->endpoints[0]->server.applicationType = UA_APPLICATIONTYPE_SERVER;
+	response->endpoints[0].server.applicationType = UA_APPLICATIONTYPE_SERVER;
 	// all the other strings are empty by initialization
 	
 	return UA_SUCCESS;

+ 9 - 9
src/ua_services_nodemanagement.c

@@ -9,14 +9,14 @@
 		goto GOTO; \
 	} } while(0) \
 
-static UA_AddNodesResult * addSingleNode(Application *app, UA_AddNodesItem *item) {
-	UA_AddNodesResult *result;
-	UA_AddNodesResult_new(&result);
+static UA_AddNodesResult addSingleNode(Application *app, UA_AddNodesItem *item) {
+	UA_AddNodesResult result;
+	UA_AddNodesResult_init(&result);
 
 	Namespace *parent_ns = UA_indexedList_findValue(app->namespaces, item->parentNodeId.nodeId.namespace);
 	// TODO: search for namespaceUris and not only ns-ids.
 	if(parent_ns == UA_NULL) {
-		result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+		result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
 		return result;
 	}
 
@@ -27,7 +27,7 @@ static UA_AddNodesResult * addSingleNode(Application *app, UA_AddNodesItem *item
 	else ns = UA_indexedList_findValue(app->namespaces, item->requestedNewNodeId.nodeId.namespace);
 
 	if(ns == UA_NULL || item->requestedNewNodeId.nodeId.namespace == 0) {
-		result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+		result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
 		return result;
 	}
 
@@ -36,10 +36,10 @@ static UA_AddNodesResult * addSingleNode(Application *app, UA_AddNodesItem *item
 	Namespace_Entry_Lock *parent_lock = UA_NULL;
 
 	CHECKED_ACTION(Namespace_get(parent_ns, &item->parentNodeId.nodeId, &parent, &parent_lock),
-				   result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
+				   result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
 
 	if(!nodeid_isnull && Namespace_contains(ns, &item->requestedNewNodeId.nodeId)) {
-		result->statusCode = UA_STATUSCODE_BADNODEIDEXISTS;
+		result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS;
 		goto ret;
 	}
 
@@ -80,8 +80,8 @@ UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request
 	response->resultsSize = nodestoaddsize;
 	UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
 	for(int i = 0; i < nodestoaddsize; i++) {
-		DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i]->browseName)));
-		response->results[i] = addSingleNode(channel->session->application, request->nodesToAdd[i]);
+		DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i].browseName)));
+		response->results[i] = addSingleNode(channel->session->application, &request->nodesToAdd[i]);
 	}
 	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
 	response->diagnosticInfosSize = -1;

+ 5 - 7
src/ua_services_view.c

@@ -3,10 +3,10 @@
 
 UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA_BrowseResponse *response) {
 	UA_Int32 retval = UA_SUCCESS;
-	DBG_VERBOSE(UA_NodeId_printf("BrowseService - view=",&(request->view.viewId)));
+	DBG_VERBOSE(UA_NodeId_printf("BrowseService - view=", &request->view.viewId));
 	UA_Int32 i = 0;
 	for (i=0;request->nodesToBrowseSize > 0 && i<request->nodesToBrowseSize;i++) {
-		UA_NodeId_printf("BrowseService - nodesToBrowse=", &(request->nodesToBrowse[i]->nodeId));
+		UA_NodeId_printf("BrowseService - nodesToBrowse=", &request->nodesToBrowse[i].nodeId);
 	}
 	return retval;
 }
@@ -17,16 +17,14 @@ 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_BROWSEPATHRESULT);
 
 	response->resultsSize = request->browsePathsSize;
 
-	UA_BrowsePathResult* path;
 	for(UA_Int32 i = 0;i<request->browsePathsSize;i++){
-		UA_BrowsePathResult_new(&path);
+		UA_BrowsePathResult_init(&response->results[i]);
 		//FIXME: implement
-		path->statusCode = UA_STATUSCODE_BADQUERYTOOCOMPLEX;
-		(response->results[i]) = path;
+		response->results[i].statusCode = UA_STATUSCODE_BADQUERYTOOCOMPLEX;
 	}
 
 	return retval;

+ 1 - 1
include/ua_statuscodes.h

@@ -1,7 +1,7 @@
 #ifndef OPCUA_STATUSCODES_H_
 #define OPCUA_STATUSCODES_H_
 
-#include "ua_basictypes.h"
+#include "ua_types.h"
 
 static const UA_StatusCode UA_STATUSCODE_GOOD = 0x00;
 static const UA_StatusCode UA_STATUSCODE_BADUNEXPECTEDERROR = 0x80010000; // An unexpected error occurred.

+ 314 - 237
src/ua_transport.c

@@ -1,148 +1,167 @@
 #include "ua_transport.h"
+#include "ua_types_encoding_binary.h"
 #include "stdio.h"
 
+UA_TYPE_DEFAULT(UA_MessageType)
 UA_Int32 UA_MessageType_calcSize(UA_MessageType const * ptr){
 	if(ptr==UA_NULL){return sizeof(UA_MessageType);}
 	return 0
 	 + 3 * sizeof(UA_Byte);
 }
 
-UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const * src, UA_Int32* pos, UA_ByteString* dst){
+UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const * src, UA_ByteString* dst, UA_UInt32 *offset){
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Byte tmpBuf[3];
 	tmpBuf[0] = (UA_Byte)((((UA_Int32)*src) >> 16) );
 	tmpBuf[1] = (UA_Byte)((((UA_Int32)*src) >> 8));
 	tmpBuf[2] = (UA_Byte)(((UA_Int32)*src));
 
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[0]),pos,dst);
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[1]),pos,dst);
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[2]),pos,dst);
+	retval |= UA_Byte_encodeBinary(&(tmpBuf[0]),dst,offset);
+	retval |= UA_Byte_encodeBinary(&(tmpBuf[1]),dst,offset);
+	retval |= UA_Byte_encodeBinary(&(tmpBuf[2]),dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_MessageType* dst){
+UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_MessageType* dst){
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Byte tmpBuf[3];
-	retval |= UA_Byte_decodeBinary(src,pos,&(tmpBuf[0])); //messageType to Byte representation
-	retval |= UA_Byte_decodeBinary(src,pos,&(tmpBuf[1]));
-	retval |= UA_Byte_decodeBinary(src,pos,&(tmpBuf[2]));
+	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[0])); //messageType to Byte representation
+	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[1]));
+	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[2]));
 	*dst = (UA_MessageType)((UA_Int32)(tmpBuf[0]<<16) + (UA_Int32)(tmpBuf[1]<<8) + (UA_Int32)(tmpBuf[2]));
 	return retval;
 }
-UA_TYPE_METHOD_DELETE_FREE(UA_MessageType)
-UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_MessageType)
+
 void UA_MessageType_printf(char *label, UA_MessageType* p) {
 	UA_Byte* b = (UA_Byte*) p;
 	printf("%s{%c%c%c}\n", label, b[2],b[1],b[0]);
 }
 
-UA_Int32 UA_OPCUATcpMessageHeader_calcSize(UA_OPCUATcpMessageHeader const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpMessageHeader);}
-	return 0
-	 + UA_MessageType_calcSize(&(ptr->messageType)) // messageType
+UA_Int32 UA_OPCUATcpMessageHeader_calcSizeBinary(UA_OPCUATcpMessageHeader const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpMessageHeader);
+    	return 0
+	 + sizeof(UA_UInt32) // messageType
 	 + sizeof(UA_Byte) // isFinal
 	 + sizeof(UA_UInt32) // messageSize
 	;
 }
 
-UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_MessageType_encodeBinary(&(src->messageType),pos,dst);
-	retval |= UA_Byte_encodeBinary(&(src->isFinal),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->messageSize),pos,dst);
+UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->messageType,dst,offset);
+	retval |= UA_Byte_encodeBinary(&src->isFinal,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->messageSize,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpMessageHeader* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpMessageHeader * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_OPCUATcpMessageHeader_init(dst);
-	CHECKED_DECODE(UA_MessageType_decodeBinary(src,pos,&(dst->messageType)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_Byte_decodeBinary(src,pos,&(dst->isFinal)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->messageSize)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->messageType), UA_OPCUATcpMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_Byte_decodeBinary(src,offset,&dst->isFinal), UA_OPCUATcpMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->messageSize), UA_OPCUATcpMessageHeader_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpMessageHeader_delete(UA_OPCUATcpMessageHeader* p) {
+UA_Int32 UA_OPCUATcpMessageHeader_delete(UA_OPCUATcpMessageHeader *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_OPCUATcpMessageHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader* p) {
-	UA_Int32 retval = UA_SUCCESS;
+}
+
+UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpMessageHeader_init(UA_OPCUATcpMessageHeader * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Byte_init(&(p->isFinal));
-	retval |= UA_UInt32_init(&(p->messageSize));
+UA_Int32 UA_OPCUATcpMessageHeader_init(UA_OPCUATcpMessageHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->messageType);
+	retval |= UA_Byte_init(&p->isFinal);
+	retval |= UA_UInt32_init(&p->messageSize);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_OPCUATcpMessageHeader)
-UA_Int32 UA_OPCUATcpHelloMessage_calcSize(UA_OPCUATcpHelloMessage const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpHelloMessage);}
-	return 0
+UA_TYPE_NEW_DEFAULT(UA_OPCUATcpMessageHeader)
+UA_Int32 UA_OPCUATcpMessageHeader_copy(const UA_OPCUATcpMessageHeader *src,UA_OPCUATcpMessageHeader *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_OPCUATcpMessageHeader));
+	return retval;
+}
+
+UA_Int32 UA_OPCUATcpHelloMessage_calcSizeBinary(UA_OPCUATcpHelloMessage const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpHelloMessage);
+    	return 0
 	 + sizeof(UA_UInt32) // protocolVersion
 	 + sizeof(UA_UInt32) // receiveBufferSize
 	 + sizeof(UA_UInt32) // sendBufferSize
 	 + sizeof(UA_UInt32) // maxMessageSize
 	 + sizeof(UA_UInt32) // maxChunkCount
-	 + UA_String_calcSize(&(ptr->endpointUrl))
+	 + UA_String_calcSizeBinary(&ptr->endpointUrl)
 	;
 }
 
-UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&(src->protocolVersion),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->receiveBufferSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->sendBufferSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->maxMessageSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->maxChunkCount),pos,dst);
-	retval |= UA_String_encodeBinary(&(src->endpointUrl),pos,dst);
+UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->protocolVersion,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->receiveBufferSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->sendBufferSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->maxMessageSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->maxChunkCount,dst,offset);
+	retval |= UA_String_encodeBinary(&src->endpointUrl,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpHelloMessage* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpHelloMessage * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_OPCUATcpHelloMessage_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_String_decodeBinary(src,pos,&(dst->endpointUrl)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->protocolVersion), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->receiveBufferSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sendBufferSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxMessageSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxChunkCount), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_String_decodeBinary(src,offset,&dst->endpointUrl), UA_OPCUATcpHelloMessage_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpHelloMessage_delete(UA_OPCUATcpHelloMessage* p) {
+UA_Int32 UA_OPCUATcpHelloMessage_delete(UA_OPCUATcpHelloMessage *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_OPCUATcpHelloMessage_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage* p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_String_deleteMembers(&(p->endpointUrl));
+}
+
+UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_String_deleteMembers(&p->endpointUrl);
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpHelloMessage_init(UA_OPCUATcpHelloMessage * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&(p->protocolVersion));
-	retval |= UA_UInt32_init(&(p->receiveBufferSize));
-	retval |= UA_UInt32_init(&(p->sendBufferSize));
-	retval |= UA_UInt32_init(&(p->maxMessageSize));
-	retval |= UA_UInt32_init(&(p->maxChunkCount));
-	retval |= UA_String_init(&(p->endpointUrl));
+UA_Int32 UA_OPCUATcpHelloMessage_init(UA_OPCUATcpHelloMessage *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->protocolVersion);
+	retval |= UA_UInt32_init(&p->receiveBufferSize);
+	retval |= UA_UInt32_init(&p->sendBufferSize);
+	retval |= UA_UInt32_init(&p->maxMessageSize);
+	retval |= UA_UInt32_init(&p->maxChunkCount);
+	retval |= UA_String_init(&p->endpointUrl);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_OPCUATcpHelloMessage)
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpAcknowledgeMessage);}
-	return 0
+UA_TYPE_NEW_DEFAULT(UA_OPCUATcpHelloMessage)
+UA_Int32 UA_OPCUATcpHelloMessage_copy(const UA_OPCUATcpHelloMessage *src,UA_OPCUATcpHelloMessage *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_OPCUATcpHelloMessage));
+	retval |= UA_String_copy(&src->endpointUrl,&dst->endpointUrl);
+	return retval;
+}
+
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(UA_OPCUATcpAcknowledgeMessage const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpAcknowledgeMessage);
+    	return 0
 	 + sizeof(UA_UInt32) // protocolVersion
 	 + sizeof(UA_UInt32) // receiveBufferSize
 	 + sizeof(UA_UInt32) // sendBufferSize
@@ -151,313 +170,371 @@ UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage co
 	;
 }
 
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&(src->protocolVersion),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->receiveBufferSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->sendBufferSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->maxMessageSize),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->maxChunkCount),pos,dst);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->protocolVersion,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->receiveBufferSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->sendBufferSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->maxMessageSize,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->maxChunkCount,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpAcknowledgeMessage* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpAcknowledgeMessage * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_OPCUATcpAcknowledgeMessage_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->protocolVersion), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->receiveBufferSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sendBufferSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxMessageSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxChunkCount), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_delete(UA_OPCUATcpAcknowledgeMessage* p) {
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_delete(UA_OPCUATcpAcknowledgeMessage *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_OPCUATcpAcknowledgeMessage_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessage* p) {
-	UA_Int32 retval = UA_SUCCESS;
+}
+
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessage *p) {
+    	UA_Int32 retval = UA_SUCCESS;
 	return retval;
 }
 
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_init(UA_OPCUATcpAcknowledgeMessage * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&(p->protocolVersion));
-	retval |= UA_UInt32_init(&(p->receiveBufferSize));
-	retval |= UA_UInt32_init(&(p->sendBufferSize));
-	retval |= UA_UInt32_init(&(p->maxMessageSize));
-	retval |= UA_UInt32_init(&(p->maxChunkCount));
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_init(UA_OPCUATcpAcknowledgeMessage *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->protocolVersion);
+	retval |= UA_UInt32_init(&p->receiveBufferSize);
+	retval |= UA_UInt32_init(&p->sendBufferSize);
+	retval |= UA_UInt32_init(&p->maxMessageSize);
+	retval |= UA_UInt32_init(&p->maxChunkCount);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_OPCUATcpAcknowledgeMessage)
-UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageHeader);}
-	return 0
-	 // + UA_OPCUATcpMessageHeader_calcSize(&(ptr->messageHeader))
+UA_TYPE_NEW_DEFAULT(UA_OPCUATcpAcknowledgeMessage)
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_copy(const UA_OPCUATcpAcknowledgeMessage *src,UA_OPCUATcpAcknowledgeMessage *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_OPCUATcpAcknowledgeMessage));
+	return retval;
+}
+
+UA_Int32 UA_SecureConversationMessageHeader_calcSizeBinary(UA_SecureConversationMessageHeader const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageHeader);
+    	return 0
+	 + sizeof(UA_OPCUATcpMessageHeader) // messageHeader CHECK: delete this or use in binary_secure.c
 	 + sizeof(UA_UInt32) // secureChannelId
 	;
 }
 
-UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	// retval |= UA_OPCUATcpMessageHeader_encodeBinary(&(src->messageHeader),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->secureChannelId),pos,dst);
+UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_OPCUATcpMessageHeader_encodeBinary(&src->messageHeader,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->secureChannelId,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageHeader * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_SecureConversationMessageHeader_init(dst);
-	// CHECKED_DECODE(UA_OPCUATcpMessageHeader_decodeBinary(src,pos,&(dst->messageHeader)), UA_SecureConversationMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->secureChannelId)), UA_SecureConversationMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_OPCUATcpMessageHeader_decodeBinary(src,offset,&dst->messageHeader), UA_SecureConversationMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->secureChannelId), UA_SecureConversationMessageHeader_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader* p) {
+UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_SecureConversationMessageHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader* p) {
-	UA_Int32 retval = UA_SUCCESS;
-	// retval |= UA_OPCUATcpMessageHeader_deleteMembers(&(p->messageHeader));
+}
+
+UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	// retval |= UA_OPCUATcpMessageHeader_init(&(p->messageHeader));
-	retval |= UA_UInt32_init(&(p->secureChannelId));
+UA_Int32 UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_OPCUATcpMessageHeader_init(&p->messageHeader);
+	retval |= UA_UInt32_init(&p->secureChannelId);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_SecureConversationMessageHeader)
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSize(UA_AsymmetricAlgorithmSecurityHeader const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_AsymmetricAlgorithmSecurityHeader);}
-	return 0
-	 + UA_ByteString_calcSize(&(ptr->securityPolicyUri))
-	 + UA_ByteString_calcSize(&(ptr->senderCertificate))
-	 + UA_ByteString_calcSize(&(ptr->receiverCertificateThumbprint))
-	 // + sizeof(UA_UInt32) // requestId
+UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageHeader)
+UA_Int32 UA_SecureConversationMessageHeader_copy(const UA_SecureConversationMessageHeader *src,UA_SecureConversationMessageHeader *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_SecureConversationMessageHeader));
+	return retval;
+}
+
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_AsymmetricAlgorithmSecurityHeader const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_AsymmetricAlgorithmSecurityHeader);
+    	return 0
+	 + UA_ByteString_calcSizeBinary(&ptr->securityPolicyUri)
+	 + UA_ByteString_calcSizeBinary(&ptr->senderCertificate)
+	 + UA_ByteString_calcSizeBinary(&ptr->receiverCertificateThumbprint)
+			//	 + sizeof(UA_UInt32) // requestId
 	;
 }
 
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorithmSecurityHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_encodeBinary(&(src->securityPolicyUri),pos,dst);
-	retval |= UA_ByteString_encodeBinary(&(src->senderCertificate),pos,dst);
-	retval |= UA_ByteString_encodeBinary(&(src->receiverCertificateThumbprint),pos,dst);
-	// retval |= UA_UInt32_encodeBinary(&(src->requestId),pos,dst);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorithmSecurityHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ByteString_encodeBinary(&src->securityPolicyUri,dst,offset);
+	retval |= UA_ByteString_encodeBinary(&src->senderCertificate,dst,offset);
+	retval |= UA_ByteString_encodeBinary(&src->receiverCertificateThumbprint,dst,offset);
+	//	retval |= UA_UInt32_encodeBinary(&src->requestId,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_AsymmetricAlgorithmSecurityHeader* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_AsymmetricAlgorithmSecurityHeader * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_AsymmetricAlgorithmSecurityHeader_init(dst);
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->securityPolicyUri)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->senderCertificate)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->receiverCertificateThumbprint)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	// CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->requestId)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->securityPolicyUri), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->senderCertificate), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->receiverCertificateThumbprint), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	//	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->requestId), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader* p) {
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader* p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_deleteMembers(&(p->securityPolicyUri));
-	retval |= UA_ByteString_deleteMembers(&(p->senderCertificate));
-	retval |= UA_ByteString_deleteMembers(&(p->receiverCertificateThumbprint));
+}
+
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ByteString_deleteMembers(&p->securityPolicyUri);
+	retval |= UA_ByteString_deleteMembers(&p->senderCertificate);
+	retval |= UA_ByteString_deleteMembers(&p->receiverCertificateThumbprint);
 	return retval;
 }
 
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_init(&(p->securityPolicyUri));
-	retval |= UA_ByteString_init(&(p->senderCertificate));
-	retval |= UA_ByteString_init(&(p->receiverCertificateThumbprint));
-	// retval |= UA_UInt32_init(&(p->requestId));
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ByteString_init(&p->securityPolicyUri);
+	retval |= UA_ByteString_init(&p->senderCertificate);
+	retval |= UA_ByteString_init(&p->receiverCertificateThumbprint);
+	//retval |= UA_UInt32_init(&p->requestId);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_AsymmetricAlgorithmSecurityHeader)
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSize(UA_SymmetricAlgorithmSecurityHeader const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_SymmetricAlgorithmSecurityHeader);}
-	return 0
+UA_TYPE_NEW_DEFAULT(UA_AsymmetricAlgorithmSecurityHeader)
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHeader *src,UA_AsymmetricAlgorithmSecurityHeader *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_AsymmetricAlgorithmSecurityHeader));
+	retval |= UA_ByteString_copy(&src->securityPolicyUri,&dst->securityPolicyUri);
+	retval |= UA_ByteString_copy(&src->senderCertificate,&dst->senderCertificate);
+	retval |= UA_ByteString_copy(&src->receiverCertificateThumbprint,&dst->receiverCertificateThumbprint);
+	return retval;
+}
+
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_SymmetricAlgorithmSecurityHeader const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_SymmetricAlgorithmSecurityHeader);
+    	return 0
 	 + sizeof(UA_UInt32) // tokenId
 	;
 }
 
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_encodeBinary(UA_SymmetricAlgorithmSecurityHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&(src->tokenId),pos,dst);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_encodeBinary(UA_SymmetricAlgorithmSecurityHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->tokenId,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SymmetricAlgorithmSecurityHeader* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SymmetricAlgorithmSecurityHeader * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_SymmetricAlgorithmSecurityHeader_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->tokenId)), UA_SymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->tokenId), UA_SymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader* p) {
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_SymmetricAlgorithmSecurityHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader* p) {
-	UA_Int32 retval = UA_SUCCESS;
+}
+
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
 	return retval;
 }
 
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&(p->tokenId));
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->tokenId);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_SymmetricAlgorithmSecurityHeader)
-UA_Int32 UA_SequenceHeader_calcSize(UA_SequenceHeader const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_SequenceHeader);}
-	return 0
+UA_TYPE_NEW_DEFAULT(UA_SymmetricAlgorithmSecurityHeader)
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_copy(const UA_SymmetricAlgorithmSecurityHeader *src,UA_SymmetricAlgorithmSecurityHeader *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_SymmetricAlgorithmSecurityHeader));
+	return retval;
+}
+
+UA_Int32 UA_SequenceHeader_calcSizeBinary(UA_SequenceHeader const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_SequenceHeader);
+    	return 0
 	 + sizeof(UA_UInt32) // sequenceNumber
 	 + sizeof(UA_UInt32) // requestId
 	;
 }
 
-UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&(src->sequenceNumber),pos,dst);
-	retval |= UA_UInt32_encodeBinary(&(src->requestId),pos,dst);
+UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->sequenceNumber,dst,offset);
+	retval |= UA_UInt32_encodeBinary(&src->requestId,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SequenceHeader* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SequenceHeader * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_SequenceHeader_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sequenceNumber)), UA_SequenceHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->requestId)), UA_SequenceHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sequenceNumber), UA_SequenceHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->requestId), UA_SequenceHeader_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_SequenceHeader_delete(UA_SequenceHeader* p) {
+UA_Int32 UA_SequenceHeader_delete(UA_SequenceHeader *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_SequenceHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader* p) {
-	UA_Int32 retval = UA_SUCCESS;
+}
+
+UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
 	return retval;
 }
 
-UA_Int32 UA_SequenceHeader_init(UA_SequenceHeader * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&(p->sequenceNumber));
-	retval |= UA_UInt32_init(&(p->requestId));
+UA_Int32 UA_SequenceHeader_init(UA_SequenceHeader *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->sequenceNumber);
+	retval |= UA_UInt32_init(&p->requestId);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_SequenceHeader)
-UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessageFooter const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageFooter);}
-	return 0
-	 + 0 //paddingSize is included in UA_Array_calcSize
-	 + UA_Array_calcSize(ptr->paddingSize, UA_BYTE, (void const**) ptr->padding)
+UA_TYPE_NEW_DEFAULT(UA_SequenceHeader)
+UA_Int32 UA_SequenceHeader_copy(const UA_SequenceHeader *src,UA_SequenceHeader *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_SequenceHeader));
+	return retval;
+}
+
+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)
 	 + sizeof(UA_Byte) // signature
 	;
 }
 
-UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	//retval |= UA_Int32_encodeBinary(&(src->paddingSize),pos,dst); // encode size managed by UA_Array_encodeBinary
-	retval |= UA_Array_encodeBinary((void const**) (src->padding),src->paddingSize, UA_BYTE,pos,dst);
-	retval |= UA_Byte_encodeBinary(&(src->signature),pos,dst);
+UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+		retval |= UA_Int32_encodeBinary(&src->paddingSize,dst, offset);
+	retval |= UA_Array_encodeBinary(&src->padding,src->paddingSize,UA_BYTE,dst,offset);
+	retval |= UA_Byte_encodeBinary(&src->signature,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageFooter* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageFooter * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_SecureConversationMessageFooter_init(dst);
-	CHECKED_DECODE(UA_Int32_decodeBinary(src,pos,&(dst->paddingSize)), UA_SecureConversationMessageFooter_deleteMembers(dst)); // decode size
-	CHECKED_DECODE(UA_Array_new((void***)&dst->padding, dst->paddingSize, UA_BYTE), dst->padding = UA_NULL; UA_SecureConversationMessageFooter_deleteMembers(dst));
-	CHECKED_DECODE(UA_Array_decodeBinary(src,dst->paddingSize, UA_BYTE,pos,(void *** const) (&dst->padding)), UA_SecureConversationMessageFooter_deleteMembers(dst));
-	CHECKED_DECODE(UA_Byte_decodeBinary(src,pos,&(dst->signature)), UA_SecureConversationMessageFooter_deleteMembers(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_Byte_decodeBinary(src,offset,&dst->signature), UA_SecureConversationMessageFooter_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter* p) {
+UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_SecureConversationMessageFooter_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter* p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_delete((void***)&p->padding,p->paddingSize,UA_BYTE); p->padding = UA_NULL;
+}
+
+UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_Array_delete((void**)&p->padding,p->paddingSize,UA_BYTE);
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	p->paddingSize=0;
-	p->padding=UA_NULL;
-	retval |= UA_Byte_init(&(p->signature));
+UA_Int32 UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	p->paddingSize = 0;
+	p->padding = UA_NULL;
+	retval |= UA_Byte_init(&p->signature);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_SecureConversationMessageFooter)
-UA_Int32 UA_SecureConversationMessageAbortBody_calcSize(UA_SecureConversationMessageAbortBody const * ptr) {
-	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageAbortBody);}
-	return 0
+UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageFooter)
+UA_Int32 UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMessageFooter *src,UA_SecureConversationMessageFooter *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	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);
+	return retval;
+}
+
+UA_Int32 UA_SecureConversationMessageAbortBody_calcSizeBinary(UA_SecureConversationMessageAbortBody const * ptr) {
+    	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageAbortBody);
+    	return 0
 	 + sizeof(UA_UInt32) // error
-	 + UA_String_calcSize(&(ptr->reason))
+	 + UA_String_calcSizeBinary(&ptr->reason)
 	;
 }
 
-UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const * src, UA_Int32* pos, UA_ByteString* dst) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&(src->error),pos,dst);
-	retval |= UA_String_encodeBinary(&(src->reason),pos,dst);
+UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&src->error,dst,offset);
+	retval |= UA_String_encodeBinary(&src->reason,dst,offset);
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageAbortBody* dst) {
-	UA_Int32 retval = UA_SUCCESS;
+UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageAbortBody * dst) {
+    	UA_Int32 retval = UA_SUCCESS;
 	UA_SecureConversationMessageAbortBody_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->error)), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
-	CHECKED_DECODE(UA_String_decodeBinary(src,pos,&(dst->reason)), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->error), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
+	CHECKED_DECODE(UA_String_decodeBinary(src,offset,&dst->reason), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody* p) {
+UA_Int32 UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody *p) {
 	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_SecureConversationMessageAbortBody_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
-    }
-UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody* p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_String_deleteMembers(&(p->reason));
+}
+
+UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_String_deleteMembers(&p->reason);
 	return retval;
 }
 
-UA_Int32 UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody * p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&(p->error));
-	retval |= UA_String_init(&(p->reason));
+UA_Int32 UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody *p) {
+    	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_init(&p->error);
+	retval |= UA_String_init(&p->reason);
 	return retval;
 }
 
-UA_TYPE_METHOD_NEW_DEFAULT(UA_SecureConversationMessageAbortBody)
+UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageAbortBody)
+UA_Int32 UA_SecureConversationMessageAbortBody_copy(const UA_SecureConversationMessageAbortBody *src,UA_SecureConversationMessageAbortBody *dst) {
+    	if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    	UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_SecureConversationMessageAbortBody));
+	retval |= UA_String_copy(&src->reason,&dst->reason);
+	return retval;
+}

+ 34 - 90
src/ua_transport.h

@@ -1,7 +1,8 @@
 #ifndef UA_TRANSPORT_H_
 #define UA_TRANSPORT_H_
 
-#include "opcua.h"
+#include "ua_types.h"
+#include "ua_types_encoding_binary.h"
 #include "ua_application.h"
 
 static const UA_Int32 SL_HEADER_LENGTH = 0;
@@ -39,29 +40,19 @@ enum UA_MessageType {
 	UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
 	UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
 };
-UA_Int32 UA_MessageType_calcSize(UA_MessageType const * ptr);
-UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_MessageType* dst);
-UA_Int32 UA_MessageType_delete(UA_MessageType* p);
-UA_Int32 UA_MessageType_deleteMembers(UA_MessageType* p);
+UA_TYPE_PROTOTYPES(UA_MessageType)
+UA_TYPE_BINARY_ENCODING(UA_MessageType)
 void UA_MessageType_printf(char *label, UA_MessageType* p);
 
-/** @name UA_UA_OPCUATcpMessageHeader */
 /** @brief TCP Header */
 typedef struct UA_OPCUATcpMessageHeader {
-	UA_MessageType messageType; // MessageType instead of UInt32
+	UA_UInt32 messageType;
 	UA_Byte isFinal;
 	UA_UInt32 messageSize;
 } UA_OPCUATcpMessageHeader;
-UA_Int32 UA_OPCUATcpMessageHeader_calcSize(UA_OPCUATcpMessageHeader const* ptr);
-UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpMessageHeader* dst);
-UA_Int32 UA_OPCUATcpMessageHeader_delete(UA_OPCUATcpMessageHeader* p);
-UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader* p);
-UA_Int32 UA_OPCUATcpMessageHeader_init(UA_OPCUATcpMessageHeader * p);
-UA_Int32 UA_OPCUATcpMessageHeader_new(UA_OPCUATcpMessageHeader ** p);
-
-/** @name UA_UA_OPCUATcpHelloMessage */
+UA_TYPE_PROTOTYPES(UA_OPCUATcpMessageHeader)
+UA_TYPE_BINARY_ENCODING(UA_OPCUATcpMessageHeader)
+
 /** @brief Hello Message */
 typedef struct UA_OPCUATcpHelloMessage {
 	UA_UInt32 protocolVersion;
@@ -71,15 +62,9 @@ typedef struct UA_OPCUATcpHelloMessage {
 	UA_UInt32 maxChunkCount;
 	UA_String endpointUrl;
 } UA_OPCUATcpHelloMessage;
-UA_Int32 UA_OPCUATcpHelloMessage_calcSize(UA_OPCUATcpHelloMessage const* ptr);
-UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpHelloMessage* dst);
-UA_Int32 UA_OPCUATcpHelloMessage_delete(UA_OPCUATcpHelloMessage* p);
-UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage* p);
-UA_Int32 UA_OPCUATcpHelloMessage_init(UA_OPCUATcpHelloMessage * p);
-UA_Int32 UA_OPCUATcpHelloMessage_new(UA_OPCUATcpHelloMessage ** p);
-
-/** @name UA_UA_OPCUATcpAcknowledgeMessage */
+UA_TYPE_PROTOTYPES(UA_OPCUATcpHelloMessage)
+UA_TYPE_BINARY_ENCODING(UA_OPCUATcpHelloMessage)
+
 /** @brief Acknowledge Message */
 typedef struct UA_OPCUATcpAcknowledgeMessage {
 	UA_UInt32 protocolVersion;
@@ -88,98 +73,57 @@ typedef struct UA_OPCUATcpAcknowledgeMessage {
 	UA_UInt32 maxMessageSize;
 	UA_UInt32 maxChunkCount;
 } UA_OPCUATcpAcknowledgeMessage;
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage const* ptr);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpAcknowledgeMessage* dst);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_delete(UA_OPCUATcpAcknowledgeMessage* p);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessage* p);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_init(UA_OPCUATcpAcknowledgeMessage * p);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_new(UA_OPCUATcpAcknowledgeMessage ** p);
-
-/** @name UA_UA_SecureConversationMessageHeader */
+UA_TYPE_PROTOTYPES(UA_OPCUATcpAcknowledgeMessage)
+UA_TYPE_BINARY_ENCODING(UA_OPCUATcpAcknowledgeMessage)
+
 /** @brief Secure Layer Sequence Header */
 typedef struct UA_SecureConversationMessageHeader {
-	// UA_OPCUATcpMessageHeader messageHeader; // Treated with custom code
+	UA_OPCUATcpMessageHeader messageHeader;
 	UA_UInt32 secureChannelId;
 } UA_SecureConversationMessageHeader;
-UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const* ptr);
-UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst);
-UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader* p);
-UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader* p);
-UA_Int32 UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader * p);
-UA_Int32 UA_SecureConversationMessageHeader_new(UA_SecureConversationMessageHeader ** p);
-
-/** @name UA_UA_AsymmetricAlgorithmSecurityHeader */
+UA_TYPE_PROTOTYPES(UA_SecureConversationMessageHeader)
+UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageHeader)
+
 /** @brief Security Header> */
 typedef struct UA_AsymmetricAlgorithmSecurityHeader {
 	UA_ByteString securityPolicyUri;
 	UA_ByteString senderCertificate;
 	UA_ByteString receiverCertificateThumbprint;
-	// UA_UInt32 requestId; // Dealt with in the SequenceHeader
+	UA_UInt32 requestId;
 } UA_AsymmetricAlgorithmSecurityHeader;
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSize(UA_AsymmetricAlgorithmSecurityHeader const* ptr);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorithmSecurityHeader const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_AsymmetricAlgorithmSecurityHeader* dst);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader* p);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader* p);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader * p);
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_new(UA_AsymmetricAlgorithmSecurityHeader ** p);
-
-/** @name UA_UA_SymmetricAlgorithmSecurityHeader */
+UA_TYPE_PROTOTYPES(UA_AsymmetricAlgorithmSecurityHeader)
+UA_TYPE_BINARY_ENCODING(UA_AsymmetricAlgorithmSecurityHeader)
+
 /** @brief Secure Layer Symmetric Algorithm Header */
 typedef struct UA_SymmetricAlgorithmSecurityHeader {
 	UA_UInt32 tokenId;
 } UA_SymmetricAlgorithmSecurityHeader;
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSize(UA_SymmetricAlgorithmSecurityHeader const* ptr);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_encodeBinary(UA_SymmetricAlgorithmSecurityHeader const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SymmetricAlgorithmSecurityHeader* dst);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader* p);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader* p);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader * p);
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_new(UA_SymmetricAlgorithmSecurityHeader ** p);
-
-/** @name UA_UA_SequenceHeader */
+UA_TYPE_PROTOTYPES(UA_SymmetricAlgorithmSecurityHeader)
+UA_TYPE_BINARY_ENCODING(UA_SymmetricAlgorithmSecurityHeader)
+
 /** @brief Secure Layer Sequence Header */
 typedef struct UA_SequenceHeader {
 	UA_UInt32 sequenceNumber;
 	UA_UInt32 requestId;
 } UA_SequenceHeader;
-UA_Int32 UA_SequenceHeader_calcSize(UA_SequenceHeader const* ptr);
-UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SequenceHeader* dst);
-UA_Int32 UA_SequenceHeader_delete(UA_SequenceHeader* p);
-UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader* p);
-UA_Int32 UA_SequenceHeader_init(UA_SequenceHeader * p);
-UA_Int32 UA_SequenceHeader_new(UA_SequenceHeader ** p);
-
-/** @name UA_UA_SecureConversationMessageFooter */
+UA_TYPE_PROTOTYPES(UA_SequenceHeader)
+UA_TYPE_BINARY_ENCODING(UA_SequenceHeader)
+
 /** @brief Secure Conversation Message Footer */
 typedef struct UA_SecureConversationMessageFooter {
 	UA_Int32 paddingSize;
-	UA_Byte** padding;
+	UA_Byte* padding;
 	UA_Byte signature;
 } UA_SecureConversationMessageFooter;
-UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessageFooter const* ptr);
-UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageFooter* dst);
-UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter* p);
-UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter* p);
-UA_Int32 UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter * p);
-UA_Int32 UA_SecureConversationMessageFooter_new(UA_SecureConversationMessageFooter ** p);
-
-/** @name UA_UA_SecureConversationMessageAbortBody */
+UA_TYPE_PROTOTYPES(UA_SecureConversationMessageFooter)
+UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageFooter)
+
 /** @brief Secure Conversation Message Abort Body */
 typedef struct UA_SecureConversationMessageAbortBody {
 	UA_UInt32 error;
 	UA_String reason;
 } UA_SecureConversationMessageAbortBody;
-UA_Int32 UA_SecureConversationMessageAbortBody_calcSize(UA_SecureConversationMessageAbortBody const* ptr);
-UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const* src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageAbortBody* dst);
-UA_Int32 UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody* p);
-UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody* p);
-UA_Int32 UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody * p);
-UA_Int32 UA_SecureConversationMessageAbortBody_new(UA_SecureConversationMessageAbortBody ** p);
+UA_TYPE_PROTOTYPES(UA_SecureConversationMessageAbortBody)
+UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageAbortBody)
 
 #endif /* UA_TRANSPORT_H_ */

+ 12 - 14
src/ua_transport_binary.c

@@ -11,14 +11,13 @@ static UA_Int32 TL_check(TL_Connection* connection, UA_ByteString* msg) {
 	return UA_SUCCESS;
 }
 
-static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* msg, UA_Int32* pos) {
+static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* offset) {
 	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 tmpPos = 0;
 	UA_OPCUATcpHelloMessage helloMessage;
 
 	if (connection->connectionState == CONNECTIONSTATE_CLOSED) {
 		DBG_VERBOSE(printf("TL_handleHello - extracting header information \n"));
-		UA_OPCUATcpHelloMessage_decodeBinary(msg,pos,&helloMessage);
+		UA_OPCUATcpHelloMessage_decodeBinary(msg,offset,&helloMessage);
 
 		// memorize buffer info and change mode to established
 		connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
@@ -49,15 +48,15 @@ static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* m
 		ackHeader.isFinal = 'F';
 
 		// encode header and message to buffer
-		tmpPos = 0;
-		ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSize(&ackMessage) + UA_OPCUATcpMessageHeader_calcSize(&ackHeader);
+		UA_UInt32 tmpOffset = 0;
+		ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(&ackMessage) + UA_OPCUATcpMessageHeader_calcSizeBinary(&ackHeader);
 		UA_ByteString *ack_msg;
 		UA_alloc((void **)&ack_msg, sizeof(UA_ByteString));
 		UA_ByteString_newMembers(ack_msg, ackHeader.messageSize);
-		UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader,&tmpPos,ack_msg);
-		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage,&tmpPos,ack_msg);
+		UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader,ack_msg,&tmpOffset);
+		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage,ack_msg,&tmpOffset);
 
-		DBG_VERBOSE(printf("TL_handleHello - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos));
+		DBG_VERBOSE(printf("TL_handleHello - Size messageToSend = %d, offset=%d\n",ackHeader.messageSize, tmpOffset));
 		DBG_VERBOSE(UA_ByteString_printx("_handleHello - ack=", ack_msg));
 		TL_Send(connection, (const UA_ByteString **) &ack_msg, 1);
 		DBG_VERBOSE(printf("TL_handleHello - finished writing\n"));
@@ -69,19 +68,19 @@ static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* m
 	return retval;
 }
 
-static UA_Int32 TL_handleOpen(TL_Connection* connection, const UA_ByteString* msg, UA_Int32* pos) {
+static UA_Int32 TL_handleOpen(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
 	if (connection->connectionState == CONNECTIONSTATE_ESTABLISHED) {
 		return SL_Channel_new(connection, msg, pos);
 	}
 	return UA_ERR_INVALID_VALUE;
 }
 
-static UA_Int32 TL_handleMsg(TL_Connection* connection, const UA_ByteString* msg, UA_Int32* pos) {
+static UA_Int32 TL_handleMsg(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
 	SL_Channel* slc = connection->secureChannel;
 	return SL_Process(slc,msg,pos);
 }
 
-static UA_Int32 TL_handleClo(TL_Connection* connection, const UA_ByteString* msg, UA_Int32* pos) {
+static UA_Int32 TL_handleClo(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
 	SL_Channel* slc = connection->secureChannel;
 	connection->connectionState = CONNECTIONSTATE_CLOSE;
     connection->secureChannel = UA_NULL;
@@ -91,12 +90,11 @@ static UA_Int32 TL_handleClo(TL_Connection* connection, const UA_ByteString* msg
 
 UA_Int32 TL_Process(TL_Connection* connection, const UA_ByteString* msg) {
 	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 pos = 0;
+	UA_UInt32 pos = 0;
 	UA_OPCUATcpMessageHeader tcpMessageHeader;
 
 	DBG_VERBOSE(printf("TL_Process - entered \n"));
-
-	if ((retval = UA_OPCUATcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader)) == UA_SUCCESS) {
+	if ((retval = UA_OPCUATcpMessageHeader_decodeBinary(msg,&pos,&tcpMessageHeader)) == UA_SUCCESS) {
 		printf("TL_Process - messageType=%.*s\n",3,msg->data);
 		switch(tcpMessageHeader.messageType) {
 		case UA_MESSAGETYPE_HEL:

+ 1 - 1
src/ua_transport_binary.h

@@ -2,7 +2,7 @@
 #define OPCUA_TRANSPORT_BINARY_H_
 #include <stdio.h>
 
-#include "opcua.h"
+#include "ua_types.h"
 
 //transport errors begin at 1000
 #define UA_ERROR_MULTIPLE_HEL 1000

+ 35 - 36
src/ua_transport_binary_secure.c

@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <memory.h> // memcpy
-#include "opcua.h"
 #include "ua_transport_binary.h"
 #include "ua_transport_binary_secure.h"
 #include "ua_transport.h"
@@ -13,7 +12,7 @@
 SL_Channel slc;
 
 static UA_Int32 SL_Send(SL_Channel* channel, const UA_ByteString * responseMessage, UA_Int32 type) {
-	UA_Int32 pos = 0;
+	UA_UInt32 offset = 0;
 	UA_Int32 isAsym = (type == UA_OPENSECURECHANNELRESPONSE_NS0); // FIXME: this is a to dumb method to determine asymmetric algorithm setting
 
 	UA_NodeId resp_nodeid;
@@ -25,12 +24,12 @@ static UA_Int32 SL_Send(SL_Channel* channel, const UA_ByteString * responseMessa
 	UA_alloc((void **)&response_gather[0], sizeof(UA_ByteString));
 	if(isAsym) {
 		UA_ByteString_newMembers((UA_ByteString *)response_gather[0], SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER +
-								 UA_AsymmetricAlgorithmSecurityHeader_calcSize(&channel->localAsymAlgSettings) +
-								 UA_NodeId_calcSize(&resp_nodeid));
+								 UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&channel->localAsymAlgSettings) +
+								 UA_NodeId_calcSizeBinary(&resp_nodeid));
 	}
 	else {
 		UA_ByteString_newMembers((UA_ByteString *)response_gather[0], 8 + 16 + // normal header + 4*32bit secure channel information
-								 UA_NodeId_calcSize(&resp_nodeid));
+								 UA_NodeId_calcSizeBinary(&resp_nodeid));
 	}
 		
 	
@@ -48,27 +47,27 @@ static UA_Int32 SL_Send(SL_Channel* channel, const UA_ByteString * responseMessa
 		header->data[1] = 'S';
 		header->data[2] = 'G';
 	}
-	pos += 3;
-	header->data[pos] = 'F';
-	pos += 1;
+	offset += 3;
+	header->data[offset] = 'F';
+	offset += 1;
 
     UA_Int32 packetSize = response_gather[0]->length + responseMessage->length;
-	UA_Int32_encodeBinary(&packetSize, &pos, header);
-	UA_UInt32_encodeBinary(&channel->securityToken.secureChannelId, &pos, header);
+	UA_Int32_encodeBinary(&packetSize,header, &offset);
+	UA_UInt32_encodeBinary(&channel->securityToken.secureChannelId, header, &offset);
 
 	/*---encode Algorithm Security Header ---*/
 	if (isAsym) {
-		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&channel->localAsymAlgSettings, &pos, header);
+		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&channel->localAsymAlgSettings, header, &offset);
 	} else {
-		UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&channel->securityToken.tokenId, &pos, header);
+		UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&channel->securityToken.tokenId, header, &offset);
 	}
 
 	/*---encode Sequence Header ---*/
-	UA_UInt32_encodeBinary(&channel->sequenceHeader.sequenceNumber, &pos, header);
-	UA_UInt32_encodeBinary(&channel->sequenceHeader.requestId, &pos, header);
+	UA_UInt32_encodeBinary(&channel->sequenceHeader.sequenceNumber, header, &offset);
+	UA_UInt32_encodeBinary(&channel->sequenceHeader.requestId, header, &offset);
 
 	/*---add payload type---*/
-	UA_NodeId_encodeBinary(&resp_nodeid, &pos, header);
+	UA_NodeId_encodeBinary(&resp_nodeid, header, &offset);
 	
 	/*---add encoded Message ---*/
     response_gather[1] = responseMessage; // is deleted in the calling function
@@ -95,25 +94,25 @@ static void init_response_header(UA_RequestHeader const * p, UA_ResponseHeader *
 #define INVOKE_SERVICE(TYPE) \
 	UA_##TYPE##Request p; \
 	UA_##TYPE##Response r; \
-	UA_##TYPE##Request_decodeBinary(msg, pos, &p); \
+	UA_##TYPE##Request_decodeBinary(msg, offset, &p); \
 	UA_##TYPE##Response_init(&r); \
 	init_response_header(&p.requestHeader, &r.responseHeader); \
 	DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
 	Service_##TYPE(channel, &p, &r); \
 	DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
-    *pos = 0; \
-	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSize(&r)); \
-	UA_##TYPE##Response_encodeBinary(&r, pos, &response_msg); \
+    *offset = 0; \
+	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
+	UA_##TYPE##Response_encodeBinary(&r, &response_msg, offset); \
 	UA_##TYPE##Request_deleteMembers(&p); \
 	UA_##TYPE##Response_deleteMembers(&r); \
 
 /** this function manages all the generic stuff for the request-response game */
-UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_Int32 *pos) {
+UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_UInt32 *offset) {
 	UA_Int32 retval = UA_SUCCESS;
 
 	// Every Message starts with a NodeID which names the serviceRequestType
 	UA_NodeId serviceRequestType;
-	UA_NodeId_decodeBinary(msg, pos, &serviceRequestType);
+	UA_NodeId_decodeBinary(msg, offset, &serviceRequestType);
 	UA_NodeId_printf("SL_processMessage - serviceRequestType=", &serviceRequestType);
 
 	UA_ByteString response_msg;
@@ -156,13 +155,13 @@ UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_Int3
 		retval = UA_ERROR;
 		UA_RequestHeader p;
 		UA_ResponseHeader r;
-		UA_RequestHeader_decodeBinary(msg,pos,&p);
+		UA_RequestHeader_decodeBinary(msg,offset,&p);
 		UA_ResponseHeader_init(&r);
 		r.requestHandle = p.requestHandle;
 		r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
-		*pos = 0;
-		UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSize(&r));
-		UA_ResponseHeader_encodeBinary(&r, pos, &response_msg);
+		*offset = 0;
+		UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSizeBinary(&r));
+		UA_ResponseHeader_encodeBinary(&r, &response_msg, offset);
 		responsetype = UA_RESPONSEHEADER_NS0;
 	}
 
@@ -175,10 +174,10 @@ UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_Int3
  *
  * @param connection
  * @param msg
- * @param pos
+ * @param offset
  * @return
  */
-UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_Int32* pos) {
+UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* offset) {
 	DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
 	UA_Int32 retval = UA_SUCCESS;
 
@@ -200,13 +199,13 @@ UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_
 	connection->secureChannel->tlConnection = connection;
 
 	/* Read the OPN message headers */
-	*pos += 4; // skip the securechannelid
-	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &connection->secureChannel->remoteAsymAlgSettings);
-	UA_SequenceHeader_decodeBinary(msg, pos, &connection->secureChannel->sequenceHeader);
+	*offset += 4; // skip the securechannelid
+	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, offset, &connection->secureChannel->remoteAsymAlgSettings);
+	UA_SequenceHeader_decodeBinary(msg, offset, &connection->secureChannel->sequenceHeader);
 	//TODO check that the sequence number is smaller than MaxUInt32 - 1024
 	//TODO check if a OpenSecureChannelRequest follows
 
-	retval |= SL_handleRequest(channel, msg, pos);
+	retval |= SL_handleRequest(channel, msg, offset);
 	return retval;
 
 	// FIXME: reject
@@ -217,23 +216,23 @@ UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_
  * (OPN,MSG,...), isFinal and MessageSize. SL_process cares for
  * secureChannelId, XASHeader and sequenceHeader
  * */
-UA_Int32 SL_Process(SL_Channel* connection, const UA_ByteString* msg, UA_Int32* pos) {
+UA_Int32 SL_Process(SL_Channel* connection, const UA_ByteString* msg, UA_UInt32* offset) {
 
 	DBG_VERBOSE(printf("SL_process - entered \n"));
 	UA_UInt32 secureChannelId;
 
 	if (connection->connectionState == CONNECTIONSTATE_ESTABLISHED) {
-		UA_UInt32_decodeBinary(msg,pos,&secureChannelId);
+		UA_UInt32_decodeBinary(msg,offset,&secureChannelId);
 
 		//FIXME: we assume SAS, need to check if AAS or SAS
 		UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
 		// if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
-		UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &symAlgSecHeader);
+		UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, offset, &symAlgSecHeader);
 
 		printf("SL_process - securityToken received=%d, expected=%d\n",secureChannelId,connection->securityToken.secureChannelId);
 		if (secureChannelId == connection->securityToken.secureChannelId) {
-			UA_SequenceHeader_decodeBinary(msg, pos, &(connection->sequenceHeader));
-			SL_handleRequest(&slc, msg, pos);
+			UA_SequenceHeader_decodeBinary(msg, offset, &(connection->sequenceHeader));
+			SL_handleRequest(&slc, msg, offset);
 		} else {
 			//TODO generate ERROR_Bad_SecureChannelUnkown
 		}

+ 3 - 3
src/ua_transport_binary_secure.h

@@ -1,6 +1,6 @@
 #ifndef OPCUA_TRANSPORT_BINARY_SECURE_H_
 #define OPCUA_TRANSPORT_BINARY_SECURE_H_
-#include "opcua.h"
+#include "ua_types.h"
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 
@@ -25,7 +25,7 @@ typedef struct SL_Channel {
 	SL_ChannelSecurityToken securityToken;
 } SL_Channel;
 
-UA_Int32 SL_Process(SL_Channel* channel, const UA_ByteString* msg, UA_Int32* pos);
-UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_Int32* pos); // this function is called from the OpenSecureChannel service
+UA_Int32 SL_Process(SL_Channel* channel, const UA_ByteString* msg, UA_UInt32* offset);
+UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* offset); // this function is called from the OpenSecureChannel service
 
 #endif /* OPCUA_TRANSPORT_BINARY_SECURE_H_ */

+ 812 - 0
src/ua_types.c

@@ -0,0 +1,812 @@
+#include <stdio.h>  // printf
+#include <stdlib.h> // alloc, free, vsnprintf
+#include <string.h>
+#include <stdarg.h> // va_start, va_end
+#include <time.h>
+#include <sys/time.h>
+#include "ua_util.h"
+#include "ua_types.h"
+#include "ua_types_generated.h"
+#include "ua_namespace_0.h"
+
+/************/
+/* Built-In */
+/************/
+
+/* Boolean */
+UA_Int32 UA_Boolean_init(UA_Boolean *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	*p = UA_FALSE;
+	return UA_SUCCESS;
+}
+
+UA_TYPE_DELETE_DEFAULT(UA_Boolean)
+UA_TYPE_DELETEMEMBERS_NOACTION(UA_Boolean)
+UA_TYPE_NEW_DEFAULT(UA_Boolean)
+UA_TYPE_COPY_DEFAULT(UA_Boolean)
+
+/* SByte */
+UA_TYPE_DEFAULT(UA_SByte)
+
+/* Byte */
+UA_TYPE_DEFAULT(UA_Byte)
+
+/* Int16 */
+UA_TYPE_DEFAULT(UA_Int16)
+
+/* UInt16 */
+UA_TYPE_DEFAULT(UA_UInt16)
+
+/* Int32 */
+UA_TYPE_DEFAULT(UA_Int32)
+
+/* UInt32 */
+UA_TYPE_DEFAULT(UA_UInt32)
+
+/* Int64 */
+UA_TYPE_DEFAULT(UA_Int64)
+
+/* UInt64 */
+UA_TYPE_DEFAULT(UA_UInt64)
+
+/* Float */
+UA_TYPE_DELETE_DEFAULT(UA_Float)
+UA_TYPE_DELETEMEMBERS_NOACTION(UA_Float)
+UA_Int32 UA_Float_init(UA_Float *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	*p = (UA_Float)0.0;
+	return UA_SUCCESS;
+}
+UA_TYPE_NEW_DEFAULT(UA_Float)
+UA_TYPE_COPY_DEFAULT(UA_Float)
+
+/* Double */
+UA_TYPE_DEFAULT(UA_Double)
+
+/* String */
+UA_TYPE_NEW_DEFAULT(UA_String)
+UA_TYPE_DELETE_DEFAULT(UA_String)
+UA_Int32 UA_String_deleteMembers(UA_String *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	if(p->data != UA_NULL) {
+		retval   |= UA_free(p->data);
+		p->data   = UA_NULL;
+		p->length = -1;
+	}
+	return retval;
+}
+UA_Int32 UA_String_copy(UA_String const *src, UA_String *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	dst->data   = UA_NULL;
+	dst->length = -1;
+	if(src->length > 0) {
+		retval |= UA_alloc((void **)&dst->data, src->length);
+		if(retval == UA_SUCCESS) {
+			retval     |= UA_memcpy((void *)dst->data, src->data, src->length);
+			dst->length = src->length;
+		}
+	}
+	return retval;
+}
+UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	dst->length = strlen(src);
+	dst->data   = UA_NULL;
+	if(dst->length > 0) {
+		retval |= UA_alloc((void **)&dst->data, dst->length);
+		if(retval == UA_SUCCESS)
+			retval |= UA_memcpy((void *)dst->data, src, dst->length);
+	}
+	return retval;
+}
+
+#define UA_STRING_COPYPRINTF_BUFSIZE 1024
+UA_Int32 UA_String_copyprintf(char const *fmt, UA_String *dst, ...) {
+	UA_Int32 retval = UA_SUCCESS;
+	char     src[UA_STRING_COPYPRINTF_BUFSIZE];
+	UA_Int32 len;
+	va_list  ap;
+	va_start(ap, dst);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+	// vsnprintf should only take a literal and no variable to be secure
+	len = vsnprintf(src, UA_STRING_COPYPRINTF_BUFSIZE, fmt, ap);
+#pragma GCC diagnostic pop
+	va_end(ap);
+	if(len < 0) {  // FIXME: old glibc 2.0 would return -1 when truncated
+		dst->length = 0;
+		dst->data   = UA_NULL;
+		retval      = UA_ERR_INVALID_VALUE;
+	} else {
+		// since glibc 2.1 vsnprintf returns len that would have resulted if buf were large enough
+		dst->length = ( len > UA_STRING_COPYPRINTF_BUFSIZE ? UA_STRING_COPYPRINTF_BUFSIZE : len );
+		retval     |= UA_alloc((void **)&dst->data, dst->length);
+		if(retval == UA_SUCCESS)
+			retval |= UA_memcpy((void *)dst->data, src, dst->length);
+	}
+	return retval;
+}
+
+UA_Int32 UA_String_init(UA_String *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	p->length = -1;
+	p->data   = UA_NULL;
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2) {
+	UA_Int32 retval;
+	if(string1->length == 0 && string2->length == 0)
+		retval = UA_EQUAL;
+	else if(string1->length == -1 && string2->length == -1)
+		retval = UA_EQUAL;
+	else if(string1->length != string2->length)
+		retval = UA_NOT_EQUAL;
+	else {
+		// casts are needed to overcome signed warnings
+		UA_Int32 is = strncmp((char const *)string1->data, (char const *)string2->data, string1->length);
+		retval = (is == 0) ? UA_EQUAL : UA_NOT_EQUAL;
+	}
+	return retval;
+}
+void UA_String_printf(char const *label, const UA_String *string) {
+	printf("%s {Length=%d, Data=%.*s}\n", label, string->length,
+	       string->length, (char *)string->data);
+}
+void UA_String_printx(char const *label, const UA_String *string) {
+	if(string == UA_NULL) {
+		printf("%s {NULL}\n", label); return;
+	}
+	printf("%s {Length=%d, Data=", label, string->length);
+	if(string->length > 0) {
+		for(UA_Int32 i = 0;i < string->length;i++) {
+			printf("%c%d", i == 0 ? '{' : ',', (string->data)[i]);
+			// if (i > 0 && !(i%20)) { printf("\n\t"); }
+		}
+	} else
+		printf("{");
+	printf("}}\n");
+}
+void UA_String_printx_hex(char const *label, const UA_String *string) {
+	printf("%s {Length=%d, Data=", label, string->length);
+	if(string->length > 0) {
+		for(UA_Int32 i = 0;i < string->length;i++)
+			printf("%c%x", i == 0 ? '{' : ',', (string->data)[i]);
+	} else
+		printf("{");
+	printf("}}\n");
+}
+
+/* DateTime */
+UA_TYPE_AS(UA_DateTime, UA_Int64)
+
+// Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
+#define FILETIME_UNIXTIME_BIAS_SEC 11644473600LL
+// Factors
+#define HUNDRED_NANOSEC_PER_USEC 10LL
+#define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
+
+// IEC 62541-6 §5.2.2.5  A DateTime value shall be encoded as a 64-bit signed integer
+// which represents the number of 100 nanosecond intervals since January 1, 1601 (UTC).
+UA_DateTime UA_DateTime_now() {
+	UA_DateTime    dateTime;
+	struct timeval tv;
+	gettimeofday(&tv, UA_NULL);
+	dateTime = (tv.tv_sec + FILETIME_UNIXTIME_BIAS_SEC)
+	           * HUNDRED_NANOSEC_PER_SEC + tv.tv_usec * HUNDRED_NANOSEC_PER_USEC;
+	return dateTime;
+}
+
+UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time) {
+	UA_DateTimeStruct dateTimeStruct;
+	//calcualting the the milli-, micro- and nanoseconds
+	UA_DateTime       timeTemp;
+	timeTemp = (time-((time/10)*10))*100; //getting the last digit -> *100 for the 100 nanaseconds resolution
+	dateTimeStruct.nanoSec  = timeTemp;   //123 456 7 -> 700 nanosec;
+	timeTemp = (time-((time/10000)*10000))/10;
+	dateTimeStruct.microSec = timeTemp;   //123 456 7 -> 456 microsec
+	timeTemp = (time-((time/10000000)*10000000))/10000;
+	dateTimeStruct.milliSec = timeTemp;   //123 456 7 -> 123 millisec
+
+	//calculating the unix time with #include <time.h>
+	time_t    timeInSec = time/10000000; //converting the nanoseconds time in unixtime
+	struct tm ts;
+	ts = *gmtime(&timeInSec);
+	//strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
+	//printf("%s\n", buf);
+	dateTimeStruct.sec    = ts.tm_sec;
+	dateTimeStruct.min    = ts.tm_min;
+	dateTimeStruct.hour   = ts.tm_hour;
+	dateTimeStruct.day    = ts.tm_mday;
+	dateTimeStruct.mounth = ts.tm_mon+1;
+	dateTimeStruct.year   = ts.tm_year + 1900;
+
+	return dateTimeStruct;
+}
+
+UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String *timeString) {
+	char *charBuf         = (char *)(*timeString).data;
+	UA_DateTimeStruct tSt = UA_DateTime_toStruct(time);
+	sprintf(charBuf, "%2d/%2d/%4d %2d:%2d:%2d.%3d.%3d.%3d", tSt.mounth, tSt.day, tSt.year,
+	        tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
+	return UA_SUCCESS;
+}
+
+/* Guid */
+UA_TYPE_DELETE_DEFAULT(UA_Guid)
+UA_Int32 UA_Guid_deleteMembers(UA_Guid *p) { return UA_SUCCESS; }
+UA_Int32 UA_Guid_compare(const UA_Guid *g1, const UA_Guid *g2) {
+	return memcmp(g1, g2, sizeof(UA_Guid));
+}
+UA_Int32 UA_Guid_init(UA_Guid *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	p->data1 = 0;
+	p->data2 = 0;
+	p->data3 = 0;
+	memset(p->data4, 8, sizeof(UA_Byte));
+	return UA_SUCCESS;
+}
+UA_TYPE_NEW_DEFAULT(UA_Guid)
+UA_Int32 UA_Guid_copy(UA_Guid const *src, UA_Guid *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void **)&dst, sizeof(UA_Guid));
+	retval |= UA_memcpy((void *)dst, (void *)src, sizeof(UA_Guid));
+	return retval;
+}
+
+/* ByteString */
+UA_TYPE_NEW_DEFAULT(UA_ByteString)
+UA_Int32 UA_ByteString_compare(const UA_ByteString *string1, const UA_ByteString *string2) {
+	return UA_String_compare((const UA_String *)string1, (const UA_String *)string2); }
+void UA_ByteString_printf(char *label, const UA_ByteString *string) {
+	UA_String_printf(label, (UA_String *)string); }
+void UA_ByteString_printx(char *label, const UA_ByteString *string) {
+	UA_String_printx(label, (UA_String *)string); }
+void UA_ByteString_printx_hex(char *label, const UA_ByteString *string) {
+	UA_String_printx_hex(label, (UA_String *)string); }
+
+UA_Byte       UA_Byte_securityPoliceNoneData[] = "http://opcfoundation.org/UA/SecurityPolicy#None";
+// sizeof()-1 : discard the implicit null-terminator of the c-char-string
+UA_ByteString UA_ByteString_securityPoliceNone = { sizeof(UA_Byte_securityPoliceNoneData)-1, UA_Byte_securityPoliceNoneData };
+
+UA_Int32 UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length) {
+	UA_Int32 retval = UA_SUCCESS;
+	if((retval |= UA_alloc((void **)&p->data, length)) == UA_SUCCESS)
+		p->length = length;
+	else {
+		p->length = length;
+		p->data   = UA_NULL;
+	}
+	return retval;
+}
+
+/* XmlElement */
+UA_TYPE_AS(UA_XmlElement, UA_ByteString)
+
+/* NodeId */
+UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id) {
+	return (UA_NodeId_getNamespace(id) == 0) && (UA_NodeId_getIdentifier(id) <= UA_DIAGNOSTICINFO); }
+
+UA_TYPE_DELETE_DEFAULT(UA_NodeId)
+UA_Int32 UA_NodeId_deleteMembers(UA_NodeId *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	switch(p->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		// nothing to do
+		break;
+
+	case UA_NODEIDTYPE_STRING: // Table 6, second entry
+		retval |= UA_String_deleteMembers(&p->identifier.string);
+		break;
+
+	case UA_NODEIDTYPE_GUID: // Table 6, third entry
+		retval |= UA_Guid_deleteMembers(&p->identifier.guid);
+		break;
+
+	case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
+		retval |= UA_ByteString_deleteMembers(&p->identifier.byteString);
+		break;
+	}
+	return retval;
+}
+
+void UA_NodeId_printf(char *label, const UA_NodeId *node) {
+	UA_Int32 l;
+
+	printf("%s {encodingByte=%d, namespace=%d,", label, (int)( node->encodingByte), (int)(node->namespace));
+	switch(node->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		printf("identifier=%d\n", node->identifier.numeric);
+		break;
+
+	case UA_NODEIDTYPE_STRING:
+		l = ( node->identifier.string.length < 0 ) ? 0 : node->identifier.string.length;
+		printf("identifier={length=%d, data=%.*s}",
+			   node->identifier.string.length, l,
+			   (char *)(node->identifier.string.data));
+		break;
+
+	case UA_NODEIDTYPE_BYTESTRING:
+		l = ( node->identifier.byteString.length < 0 ) ? 0 : node->identifier.byteString.length;
+		printf("identifier={Length=%d, data=%.*s}",
+			   node->identifier.byteString.length, l,
+			   (char *)(node->identifier.byteString.data));
+		break;
+
+	case UA_NODEIDTYPE_GUID:
+		printf(
+			   "guid={data1=%d, data2=%d, data3=%d, data4={length=%d, data=%.*s}}",
+			   node->identifier.guid.data1, node->identifier.guid.data2,
+			   node->identifier.guid.data3, 8,
+			   8,
+			   (char *)(node->identifier.guid.data4));
+		break;
+
+	default:
+		printf("ups! shit happens");
+		break;
+	}
+	printf("}\n");
+}
+
+UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2) {
+	if(n1 == UA_NULL || n2 == UA_NULL || n1->encodingByte != n2->encodingByte || n1->namespace != n2->namespace)
+		return UA_NOT_EQUAL;
+
+	switch(n1->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		if(n1->identifier.numeric == n2->identifier.numeric)
+			return UA_EQUAL;
+		else
+			return UA_NOT_EQUAL;
+
+	case UA_NODEIDTYPE_STRING:
+		return UA_String_compare(&n1->identifier.string, &n2->identifier.string);
+
+	case UA_NODEIDTYPE_GUID:
+		return UA_Guid_compare(&n1->identifier.guid, &n2->identifier.guid);
+
+	case UA_NODEIDTYPE_BYTESTRING:
+		return UA_ByteString_compare(&n1->identifier.byteString, &n2->identifier.byteString);
+	}
+	return UA_NOT_EQUAL;
+}
+
+UA_Int32 UA_NodeId_init(UA_NodeId *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	p->encodingByte = UA_NODEIDTYPE_TWOBYTE;
+	p->namespace    = 0;
+	memset(&p->identifier, 0, sizeof(p->identifier));
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_NodeId)
+UA_Int32 UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_Byte_copy(&src->encodingByte, &dst->encodingByte);
+
+	switch(src->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		// nothing to do
+		retval |= UA_UInt16_copy(&src->namespace, &dst->namespace);
+		retval |= UA_UInt32_copy(&src->identifier.numeric, &dst->identifier.numeric);
+		break;
+
+	case UA_NODEIDTYPE_STRING: // Table 6, second entry
+		retval |= UA_String_copy(&src->identifier.string, &dst->identifier.string);
+		break;
+
+	case UA_NODEIDTYPE_GUID: // Table 6, third entry
+		retval |= UA_Guid_copy(&src->identifier.guid, &dst->identifier.guid);
+		break;
+
+	case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
+		retval |= UA_ByteString_copy(&src->identifier.byteString, &dst->identifier.byteString);
+		break;
+	}
+	return retval;
+}
+
+UA_Boolean UA_NodeId_isNull(const UA_NodeId *p) {
+	switch(p->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+		if(p->identifier.numeric != 0) return UA_FALSE;
+		break;
+
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		if(p->namespace != 0 || p->identifier.numeric != 0) return UA_FALSE;
+		break;
+
+	case UA_NODEIDTYPE_STRING:
+		if(p->namespace != 0 || p->identifier.string.length != 0) return UA_FALSE;
+		break;
+
+	case UA_NODEIDTYPE_GUID:
+		if(p->namespace != 0 ||
+		   memcmp(&p->identifier.guid, (char[sizeof(UA_Guid)]) { 0 }, sizeof(UA_Guid)) != 0) return UA_FALSE;
+		break;
+
+	case UA_NODEIDTYPE_BYTESTRING:
+		if(p->namespace != 0 || p->identifier.byteString.length != 0) return UA_FALSE;
+		break;
+
+	default:
+		return UA_FALSE;
+	}
+	return UA_TRUE;
+}
+
+/* ExpandedNodeId */
+UA_TYPE_DELETE_DEFAULT(UA_ExpandedNodeId)
+UA_Int32 UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_NodeId_deleteMembers(&p->nodeId);
+	retval |= UA_String_deleteMembers(&p->namespaceUri);
+	return retval;
+}
+
+UA_Int32 UA_ExpandedNodeId_init(UA_ExpandedNodeId *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	UA_NodeId_init(&p->nodeId);
+	UA_String_init(&p->namespaceUri);
+	p->serverIndex = 0;
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_ExpandedNodeId)
+UA_Int32 UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
+	UA_NodeId_copy(&src->nodeId, &dst->nodeId);
+	UA_UInt32_copy(&src->serverIndex, &dst->serverIndex);
+	return retval;
+}
+
+UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p) {
+	return UA_NodeId_isNull(&p->nodeId);
+}
+
+/* StatusCode */
+UA_TYPE_AS(UA_StatusCode, UA_UInt32)
+
+/* QualifiedName */
+UA_Int32 UA_QualifiedName_delete(UA_QualifiedName *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_QualifiedName_deleteMembers(p);
+	retval |= UA_free(p);
+	return retval;
+}
+
+UA_Int32 UA_QualifiedName_deleteMembers(UA_QualifiedName *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_String_deleteMembers(&p->name);
+	return retval;
+}
+
+UA_Int32 UA_QualifiedName_init(UA_QualifiedName *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	UA_String_init(&p->name);
+	p->namespaceIndex = 0;
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_QualifiedName)
+UA_Int32 UA_QualifiedName_copy(UA_QualifiedName const *src, UA_QualifiedName *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void **)&dst, sizeof(UA_QualifiedName));
+	retval |= UA_String_copy(&src->name, &dst->name);
+	retval |= UA_UInt16_copy(&src->namespaceIndex, &dst->namespaceIndex);
+	return retval;
+
+}
+
+/* LocalizedText */
+UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
+UA_Int32 UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
+	return UA_SUCCESS | UA_String_deleteMembers(&p->locale) | UA_String_deleteMembers(&p->text);
+}
+
+UA_Int32 UA_LocalizedText_init(UA_LocalizedText *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	p->encodingMask = 0;
+	UA_String_init(&p->locale);
+	UA_String_init(&p->text);
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_LocalizedText)
+UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	if(dst == UA_NULL) return UA_ERROR;
+	dst->encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE | UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+	retval |= UA_String_copycstring("EN", &dst->locale);
+	retval |= UA_String_copycstring(src, &dst->text);
+	return retval;
+}
+
+UA_Int32 UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void **)&dst, sizeof(UA_LocalizedText));
+	retval |= UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
+	retval |= UA_String_copy(&src->locale, &dst->locale);
+	retval |= UA_String_copy(&src->text, &dst->text);
+	return retval;
+}
+
+/* ExtensionObject */
+UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
+UA_Int32 UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_NodeId_deleteMembers(&p->typeId);
+	retval |= UA_ByteString_deleteMembers(&p->body);
+	return retval;
+}
+UA_Int32 UA_ExtensionObject_init(UA_ExtensionObject *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	UA_ByteString_init(&p->body);
+	p->encoding = 0;
+	UA_NodeId_init(&p->typeId);
+	return UA_SUCCESS;
+}
+UA_TYPE_NEW_DEFAULT(UA_ExtensionObject)
+UA_Int32 UA_ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void **)&dst, sizeof(UA_ExtensionObject));
+	retval |= UA_Byte_copy(&src->encoding, &dst->encoding);
+	retval |= UA_ByteString_copy(&src->body, &dst->body);
+	retval |= UA_NodeId_copy(&src->typeId, &dst->typeId);
+	return retval;
+}
+
+/* DataValue */
+UA_TYPE_DELETE_DEFAULT(UA_DataValue)
+UA_Int32 UA_DataValue_deleteMembers(UA_DataValue *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Variant_deleteMembers(&p->value);
+	return retval;
+}
+UA_Int32 UA_DataValue_init(UA_DataValue *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	p->encodingMask      = 0;
+	p->serverPicoseconds = 0;
+	UA_DateTime_init(&p->serverTimestamp);
+	p->sourcePicoseconds = 0;
+	UA_DateTime_init(&p->sourceTimestamp);
+	UA_StatusCode_init(&p->status);
+	UA_Variant_init(&p->value);
+	return UA_SUCCESS;
+}
+UA_TYPE_NEW_DEFAULT(UA_DataValue)
+
+UA_Int32 UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	//TODO can be optimized by direct UA_memcpy call
+	UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
+	UA_Int16_copy(&src->serverPicoseconds, &dst->serverPicoseconds);
+	UA_DateTime_copy(&src->serverTimestamp, &dst->serverTimestamp);
+	UA_Int16_copy(&src->sourcePicoseconds, &dst->sourcePicoseconds);
+	UA_DateTime_copy(&src->sourceTimestamp, &dst->sourceTimestamp);
+	UA_StatusCode_copy(&src->status, &dst->status);
+	UA_Variant_copy(&src->value, &dst->value);
+	return retval;
+}
+
+/* Variant */
+UA_TYPE_DELETE_DEFAULT(UA_Variant)
+UA_Int32 UA_Variant_deleteMembers(UA_Variant *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	if(p->data != UA_NULL) {
+		retval |= UA_Array_delete(p->data, p->arrayLength, UA_ns0ToVTableIndex(&p->vt->typeId));
+		retval |= UA_Array_delete(p->data, p->arrayDimensionsLength, UA_INT32);
+	}
+	return retval;
+}
+
+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       = 0;
+	p->arrayDimensionsLength = 0;
+	p->vt = &UA_.types[UA_INVALIDTYPE];
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_Variant)
+
+UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
+	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];
+	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->arrayDimensions, src->arrayDimensionsLength,
+								UA_INT32, (void**)&dst->arrayDimensions);
+	}
+	return retval;
+}
+
+UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type_id, const void *value) {
+	v->encodingMask = type_id & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK;
+	if(UA_VTable_isValidType(type_id) != UA_SUCCESS) return UA_INVALIDTYPE;
+	v->vt = &UA_borrowed_.types[type_id];
+	v->data         = (void *)value;
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_Variant_copySetValue(UA_Variant *v, UA_Int32 type_id, const void *value) {
+	v->encodingMask = type_id & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK;
+	if(UA_VTable_isValidType(type_id) != UA_SUCCESS) return UA_INVALIDTYPE;
+	v->vt = &UA_.types[type_id];
+	return v->vt->copy(value, v->data);
+}
+
+UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_Int32 type_id, UA_Int32 arrayLength, const void *array) {
+	v->encodingMask = (type_id & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) | UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	if(UA_VTable_isValidType(type_id) != UA_SUCCESS) return UA_INVALIDTYPE;
+	v->vt = &UA_borrowed_.types[type_id];
+	v->arrayLength  = arrayLength;
+	v->data         = (void *)array;
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_Variant_copySetArray(UA_Variant *v, UA_Int32 type_id, UA_Int32 arrayLength, UA_UInt32 elementSize,
+                                 const void *array) {
+	v->encodingMask = (type_id & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) | UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	if(UA_VTable_isValidType(type_id) != UA_SUCCESS) return UA_INVALIDTYPE;
+	v->vt = &UA_.types[type_id];
+	v->arrayLength  = arrayLength;
+	void    *new_arr;
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc(&new_arr, arrayLength * elementSize);
+	retval |= UA_memcpy(new_arr, array, arrayLength * elementSize);
+	v->data = new_arr;
+	return UA_SUCCESS;
+}
+
+/* DiagnosticInfo */
+UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
+UA_Int32 UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	if((p->encodingMask & UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO) && p->innerDiagnosticInfo != UA_NULL) {
+		retval |= UA_DiagnosticInfo_deleteMembers(p->innerDiagnosticInfo);
+		retval |= UA_free(p->innerDiagnosticInfo);
+	}
+	return retval;
+}
+
+UA_Int32 UA_DiagnosticInfo_init(UA_DiagnosticInfo *p) {
+	if(p == UA_NULL) return UA_ERROR;
+	UA_String_init(&p->additionalInfo);
+	p->encodingMask        = 0;
+	p->innerDiagnosticInfo = UA_NULL;
+	UA_StatusCode_init(&p->innerStatusCode);
+	p->locale              = 0;
+	p->localizedText       = 0;
+	p->namespaceUri        = 0;
+	p->symbolicId          = 0;
+	return UA_SUCCESS;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_DiagnosticInfo)
+UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
+	retval |= UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
+	retval |= UA_StatusCode_copy(&src->innerStatusCode, &dst->innerStatusCode);
+	if(src->innerDiagnosticInfo) {
+		retval |= UA_alloc((void **)&dst->innerDiagnosticInfo, sizeof(UA_DiagnosticInfo));
+		if(retval == UA_SUCCESS)
+			retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
+	} else
+		dst->innerDiagnosticInfo = UA_NULL;
+	retval |= UA_Int32_copy(&src->locale, &dst->locale);
+	retval |= UA_Int32_copy(&src->localizedText, &dst->localizedText);
+	retval |= UA_Int32_copy(&src->namespaceUri, &dst->namespaceUri);
+	retval |= UA_Int32_copy(&src->symbolicId, &dst->symbolicId);
+
+	return retval;
+}
+
+/* InvalidType */
+UA_Int32 UA_InvalidType_free(UA_InvalidType *p) {
+	return UA_ERR_INVALID_VALUE;
+}
+UA_Int32 UA_InvalidType_delete(UA_InvalidType *p) {
+	return UA_ERR_INVALID_VALUE;
+}
+UA_Int32 UA_InvalidType_deleteMembers(UA_InvalidType *p) {
+	return UA_ERR_INVALID_VALUE;
+}
+UA_Int32 UA_InvalidType_init(UA_InvalidType *p) {
+	return UA_ERR_INVALID_VALUE;
+}
+UA_Int32 UA_InvalidType_copy(UA_InvalidType const *src, UA_InvalidType *dst) {
+	return UA_ERR_INVALID_VALUE;
+}
+UA_Int32 UA_InvalidType_new(UA_InvalidType **p) {
+	return UA_ERR_INVALID_VALUE;
+}
+
+/*********/
+/* Array */
+/*********/
+
+UA_Int32 UA_Array_delete(void *p, UA_Int32 noElements, UA_Int32 type) {
+	UA_Int32 retval = UA_SUCCESS;
+	char *cp = (char *)p; // so compilers allow pointer arithmetic
+	if(p != UA_NULL) {
+		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 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;
+		return retval;
+	}
+	retval = UA_Array_init(*p, noElements, type);
+	if(retval != UA_SUCCESS) {
+		UA_free(*p);
+		*p = UA_NULL;
+	}
+	return retval;
+}
+
+UA_Int32 UA_Array_init(void *p, UA_Int32 noElements, UA_Int32 type) {
+	UA_Int32 retval = UA_SUCCESS;
+	char *cp = (char *)p; // so compilers allow pointer arithmetic
+	for(UA_Int32 i=0;i<noElements && retval == UA_SUCCESS;i++) {
+		retval |= UA_.types[type].init(cp);
+		cp += UA_.types[type].memSize;
+	}
+	return retval;
+}
+
+UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void **dst) {
+	if(UA_VTable_isValidType(type) != UA_SUCCESS)
+		return UA_ERROR;
+
+	UA_Int32 retval = UA_Array_new(dst, noElements, type);
+	if(retval != UA_SUCCESS) return retval;
+	
+	char *csrc = (char *)src; // so compilers allow pointer arithmetic
+	char *cdst    = (char *)*dst;
+	for(UA_Int32 i = 0;i < noElements && retval == UA_SUCCESS;i++) {
+		retval |= UA_.types[type].copy(csrc, cdst);
+		csrc += UA_.types[type].memSize;
+		cdst += UA_.types[type].memSize;
+	}
+	return retval;
+}

+ 417 - 0
src/ua_types.h

@@ -0,0 +1,417 @@
+#ifndef UA_TYPES_H_
+#define UA_TYPES_H_
+
+#include <stdint.h>
+
+/* Function return values */
+#define UA_SUCCESS 0
+#define UA_NO_ERROR UA_SUCCESS
+#define UA_ERROR (0x01 << 31)
+#define UA_ERR_INCONSISTENT (UA_ERROR | (0x01 << 1))
+#define UA_ERR_INVALID_VALUE (UA_ERROR | (0x01 << 2))
+#define UA_ERR_NO_MEMORY (UA_ERROR | (0x01 << 3))
+#define UA_ERR_NOT_IMPLEMENTED (UA_ERROR | (0x01 << 4))
+
+/* Boolean values and null */
+#define UA_TRUE (42 == 42)
+#define TRUE UA_TRUE
+#define UA_FALSE (!UA_TRUE)
+#define FALSE UA_FALSE
+
+/* Compare values */
+#define UA_EQUAL 0
+#define UA_NOT_EQUAL (!UA_EQUAL)
+
+/** @brief A two-state logical value (true or false). */
+typedef _Bool UA_Boolean;
+
+/** @brief An integer value between −128 and 127. */
+typedef int8_t UA_SByte;
+
+/** @brief An integer value between 0 and 256. */
+typedef uint8_t UA_Byte;
+
+/** @brief An integer value between −32 768 and 32 767. */
+typedef int16_t UA_Int16;
+
+/** @brief An integer value between 0 and 65 535. */
+typedef uint16_t UA_UInt16;
+
+/** @brief An integer value between −2 147 483 648 and 2 147 483 647. */
+typedef int32_t UA_Int32;
+
+/** @brief An integer value between 0 and 429 4967 295. */
+typedef uint32_t UA_UInt32;
+
+/** @brief An integer value between −9 223 372 036 854 775 808 and 9 223 372 036 854 775 807 */
+typedef int64_t UA_Int64;
+
+/** @brief An integer value between 0 and 18 446 744 073 709 551 615. */
+typedef uint64_t UA_UInt64;
+
+/** @brief An IEEE single precision (32 bit) floating point value. */
+typedef float UA_Float;
+
+/** @brief An IEEE double precision (64 bit) floating point value. */
+typedef double UA_Double;
+
+/** @brief A sequence of Unicode characters. */
+typedef struct UA_String {
+	UA_Int32 length;
+	UA_Byte *data;
+} UA_String;
+
+/** @brief An instance in time. */
+typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
+
+/** @brief A 16 byte value that can be used as a globally unique identifier. */
+typedef struct UA_Guid {
+	UA_UInt32 data1;
+	UA_UInt16 data2;
+	UA_UInt16 data3;
+	UA_Byte   data4[8];
+} UA_Guid;
+
+/** @brief A sequence of octets. */
+typedef struct UA_ByteString {
+	UA_Int32 length;
+	UA_Byte *data;
+} UA_ByteString;
+
+/** @brief An XML element. */
+typedef struct UA_ByteString UA_XmlElement;
+
+/** @brief An identifier for a node in the address space of an OPC UA Server. */
+typedef struct UA_NodeId {
+	UA_Byte encodingByte;       //enum BID_NodeIdEncodingValuesType
+	UA_UInt16 namespace;
+	union {
+		UA_UInt32     numeric;
+		UA_String     string;
+		UA_Guid       guid;
+		UA_ByteString byteString;
+	} identifier;
+} UA_NodeId;
+
+#define UA_NODEIDTYPE_NAMESPACE_URI_FLAG 0x80
+#define UA_NODEIDTYPE_SERVERINDEX_FLAG 0x40
+#define UA_NODEIDTYPE_MASK (~(UA_NODEIDTYPE_NAMESPACE_URI_FLAG | UA_NODEIDTYPE_SERVERINDEX_FLAG))
+
+/** @brief A NodeId that allows the namespace URI to be specified instead of an index. */
+typedef struct UA_ExpandedNodeId {
+	UA_NodeId nodeId;
+	UA_String namespaceUri;
+	UA_UInt32 serverIndex;
+} UA_ExpandedNodeId;
+
+/** @brief A numeric identifier for a error or condition that is associated with a value or an operation. */
+typedef UA_UInt32 UA_StatusCode; // StatusCodes aren't an enum(=int) since 32 unsigned bits are needed. See also ua_statuscodes.h */
+
+/** @brief A name qualified by a namespace. */
+typedef struct UA_QualifiedName {
+	UA_UInt16 namespaceIndex;
+	UA_String name;
+} UA_QualifiedName;
+
+/** @brief Human readable text with an optional locale identifier. */
+typedef struct UA_LocalizedText {
+	UA_Byte   encodingMask;
+	UA_String locale;
+	UA_String text;
+} UA_LocalizedText;
+
+enum UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_enum {
+	UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE = 0x01,
+	UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT   = 0x02
+};
+
+/** @brief A structure that contains an application specific data type that may not be recognized by the receiver. */
+typedef struct UA_ExtensionObject {
+	UA_NodeId     typeId;
+	UA_Byte       encoding;     // Type of the enum UA_ExtensionObjectEncodingMaskType
+	UA_ByteString body;         // contains either the bytestring or a pointer to the memory-object
+} UA_ExtensionObject;
+
+enum UA_ExtensionObject_EncodingMaskType_enum {
+	UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED  = 0x00,
+	UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING = 0x01,
+	UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML        = 0x02
+};
+
+struct UA_VTable_Entry; // forwards declaration
+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_Int32    arrayLength;   // total number of elements
+	UA_Int32    arrayDimensionsLength;
+	UA_Int32  *arrayDimensions;
+	void      *data;
+} UA_Variant;
+
+/* VariantBinaryEncoding - Part: 6, Chapter: 5.2.2.16, Page: 22 */
+enum UA_VARIANT_ENCODINGMASKTYPE_enum {
+	UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F,            // bits 0:5
+	UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS  = (0x01 << 6),     // bit 6
+	UA_VARIANT_ENCODINGMASKTYPE_ARRAY       = (0x01 << 7)      // bit 7
+};
+
+/** @brief A data value with an associated status code and timestamps. */
+typedef struct UA_DataValue {
+	UA_Byte       encodingMask;
+	UA_Variant    value;
+	UA_StatusCode status;
+	UA_DateTime   sourceTimestamp;
+	UA_Int16      sourcePicoseconds;
+	UA_DateTime   serverTimestamp;
+	UA_Int16      serverPicoseconds;
+} UA_DataValue;
+
+enum UA_DATAVALUE_ENCODINGMASKTYPE_enum {
+	UA_DATAVALUE_ENCODINGMASK_VARIANT           = 0x01,
+	UA_DATAVALUE_ENCODINGMASK_STATUSCODE        = 0x02,
+	UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP   = 0x04,
+	UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP   = 0x08,
+	UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS = 0x10,
+	UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS = 0x20
+};
+
+/** @brief A structure that contains detailed error and diagnostic information associated with a StatusCode. */
+typedef struct UA_DiagnosticInfo {
+	UA_Byte       encodingMask;     // Type of the Enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE
+	UA_Int32      symbolicId;
+	UA_Int32      namespaceUri;
+	UA_Int32      localizedText;
+	UA_Int32      locale;
+	UA_String     additionalInfo;
+	UA_StatusCode innerStatusCode;
+	struct UA_DiagnosticInfo *innerDiagnosticInfo;
+} UA_DiagnosticInfo;
+
+enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
+	UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID          = 0x01,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE           = 0x02,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT       = 0x04,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE              = 0x08,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO      = 0x10,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE     = 0x20,
+	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
+};
+
+/** @brief Type use internally to denote an invalid datatype. */
+typedef void UA_InvalidType;
+
+/*************/
+/* Functions */
+/*************/
+
+#define UA_TYPE_PROTOTYPES(TYPE)      \
+    UA_Int32 TYPE##_new(TYPE **p);           \
+    UA_Int32 TYPE##_init(TYPE * p);          \
+    UA_Int32 TYPE##_delete(TYPE * p);        \
+    UA_Int32 TYPE##_deleteMembers(TYPE * p); \
+    UA_Int32 TYPE##_copy(const TYPE *src, TYPE *dst);
+
+/* Functions for all types */
+UA_TYPE_PROTOTYPES(UA_Boolean)
+UA_TYPE_PROTOTYPES(UA_SByte)
+UA_TYPE_PROTOTYPES(UA_Byte)
+UA_TYPE_PROTOTYPES(UA_Int16)
+UA_TYPE_PROTOTYPES(UA_UInt16)
+UA_TYPE_PROTOTYPES(UA_Int32)
+UA_TYPE_PROTOTYPES(UA_UInt32)
+UA_TYPE_PROTOTYPES(UA_Int64)
+UA_TYPE_PROTOTYPES(UA_UInt64)
+UA_TYPE_PROTOTYPES(UA_Float)
+UA_TYPE_PROTOTYPES(UA_Double)
+UA_TYPE_PROTOTYPES(UA_String)
+UA_TYPE_PROTOTYPES(UA_DateTime)
+UA_TYPE_PROTOTYPES(UA_Guid)
+UA_TYPE_PROTOTYPES(UA_ByteString)
+UA_TYPE_PROTOTYPES(UA_XmlElement)
+UA_TYPE_PROTOTYPES(UA_NodeId)
+UA_TYPE_PROTOTYPES(UA_ExpandedNodeId)
+UA_TYPE_PROTOTYPES(UA_StatusCode)
+UA_TYPE_PROTOTYPES(UA_QualifiedName)
+UA_TYPE_PROTOTYPES(UA_LocalizedText)
+UA_TYPE_PROTOTYPES(UA_ExtensionObject)
+UA_TYPE_PROTOTYPES(UA_DataValue)
+UA_TYPE_PROTOTYPES(UA_Variant)
+UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
+UA_TYPE_PROTOTYPES(UA_InvalidType)
+
+/* String */
+UA_Int32 UA_String_copycstring(char const *src, UA_String *dst);
+UA_Int32 UA_String_copyprintf(char const *fmt, UA_String *dst, ...);
+UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2);
+void UA_String_printf(char const *label, const UA_String *string);
+void UA_String_printx(char const *label, const UA_String *string);
+void UA_String_printx_hex(char const *label, const UA_String *string);
+
+/* DateTime */
+UA_DateTime UA_DateTime_now();
+typedef struct UA_DateTimeStruct {
+	UA_Int16 nanoSec;
+	UA_Int16 microSec;
+	UA_Int16 milliSec;
+	UA_Int16 sec;
+	UA_Int16 min;
+	UA_Int16 hour;
+	UA_Int16 day;
+	UA_Int16 mounth;
+	UA_Int16 year;
+} UA_DateTimeStruct;
+UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time);
+UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String *timeString);
+
+/* Guid */
+UA_Int32 UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2);
+
+/* ByteString */
+UA_Int32 UA_ByteString_equal(const UA_ByteString *string1, const UA_ByteString *string2);
+UA_Int32 UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length);
+void UA_ByteString_printf(char *label, const UA_ByteString *string);
+void UA_ByteString_printx(char *label, const UA_ByteString *string);
+void UA_ByteString_printx_hex(char *label, const UA_ByteString *string);
+
+/* NodeId */
+UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2);
+void UA_NodeId_printf(char *label, const UA_NodeId *node);
+UA_Boolean UA_NodeId_isNull(const UA_NodeId *p);
+UA_Int16 UA_NodeId_getNamespace(UA_NodeId const *id);
+UA_Int16 UA_NodeId_getIdentifier(UA_NodeId const *id);
+UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id);
+
+/* ExpandedNodeId */
+UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p);
+
+/* LocalizedText */
+UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
+
+/* Variant */
+UA_Int32 UA_Variant_copySetValue(UA_Variant *v, UA_Int32 type, const void *data);
+UA_Int32 UA_Variant_copySetArray(UA_Variant *v, UA_Int32 type_id, UA_Int32 arrayLength, UA_UInt32 elementSize,
+                                 const void *array);
+/** @brief Functions UA_Variant_borrowSetValue and ..Array allow to define
+   variants whose payload will not be deleted. This is achieved by a second
+   vtable. The functionality can be used e.g. when UA_VariableNodes point into a
+   "father" structured object that is stored in an UA_VariableNode itself. */
+UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type, const void *data);                       // Take care not to free the data before the variant.
+UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_Int32 type, UA_Int32 arrayLength, const void *data); // Take care not to free the data before the variant.
+
+/* 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);
+
+/* @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);
+
+/**********/
+/* VTable */
+/**********/
+
+/* @brief Returns the size of the encoded element.*/
+typedef UA_Int32 (*UA_calcSize)(const void * p);
+
+/* @brief The encoding function allocates the target bytestring. */
+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 struct UA_Encoding {
+	UA_calcSize calcSize;
+	UA_encode encode;
+	UA_decode decode;
+} UA_Encoding;
+
+struct UA_VTable_Entry {
+	UA_NodeId     typeId;
+	UA_Byte      *name;
+	UA_Int32      (*new)(void **p);
+	UA_Int32      (*init)(void *p);
+	UA_Int32      (*copy)(void const *src, void *dst);
+	UA_Int32      (*delete)(void *p);
+	UA_Int32      (*deleteMembers)(void *p);
+	UA_UInt32     memSize;   // size of the struct only in memory (no dynamic components)
+	UA_Encoding encodings[2]; // binary, xml, ...
+};
+
+typedef UA_Int32 (*UA_nodeIdToVTableIndex)(const UA_NodeId *id);
+typedef struct UA_VTable {
+	UA_nodeIdToVTableIndex getTypeIndex;
+	UA_VTable_Entry *types;
+} UA_VTable;
+
+/***********************************/
+/* Macros for type implementations */
+/***********************************/
+
+#define UA_TYPE_DEFAULT(TYPE)					\
+	UA_TYPE_DELETE_DEFAULT(TYPE)				\
+	UA_TYPE_DELETEMEMBERS_NOACTION(TYPE)		\
+	UA_TYPE_INIT_DEFAULT(TYPE)					\
+	UA_TYPE_NEW_DEFAULT(TYPE)					\
+	UA_TYPE_COPY_DEFAULT(TYPE)					\
+
+#define UA_TYPE_NEW_DEFAULT(TYPE)                                 \
+    UA_Int32 TYPE##_new(TYPE **p) {                               \
+		UA_Int32 retval = UA_SUCCESS;                             \
+		retval |= UA_alloc((void **)p, sizeof(TYPE));			  \
+		retval |= TYPE##_init(*p);                                \
+		return retval;                                            \
+	}
+
+#define UA_TYPE_INIT_DEFAULT(TYPE)         \
+    UA_Int32 TYPE##_init(TYPE * p) {       \
+		if(p == UA_NULL) return UA_ERROR;  \
+		*p = (TYPE)0;                      \
+		return UA_SUCCESS;                 \
+	}
+
+#define UA_TYPE_INIT_AS(TYPE, TYPE_AS)       \
+    UA_Int32 TYPE##_init(TYPE * p) {         \
+		return TYPE_AS##_init((TYPE_AS *)p); \
+	}
+
+#define UA_TYPE_DELETE_DEFAULT(TYPE)	   \
+    UA_Int32 TYPE##_delete(TYPE *p) {      \
+		UA_Int32 retval = UA_SUCCESS;      \
+		retval |= TYPE##_deleteMembers(p); \
+		retval |= UA_free(p);              \
+		return retval;                     \
+	}
+
+#define UA_TYPE_DELETE_AS(TYPE, TYPE_AS) \
+    UA_Int32 TYPE##_delete(TYPE * p) { return TYPE_AS##_delete((TYPE_AS *)p); }
+
+#define UA_TYPE_DELETEMEMBERS_NOACTION(TYPE) \
+    UA_Int32 TYPE##_deleteMembers(TYPE * p) { return UA_SUCCESS; }
+
+#define UA_TYPE_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
+    UA_Int32 TYPE##_deleteMembers(TYPE * p) { return TYPE_AS##_deleteMembers((TYPE_AS *)p); }
+
+/* Use only when the type has no arrays. Otherwise, implement deep copy */
+#define UA_TYPE_COPY_DEFAULT(TYPE)										\
+    UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {					\
+		UA_Int32 retval = UA_SUCCESS;									\
+		retval |= UA_memcpy(dst, src, sizeof(TYPE));					\
+		return retval;													\
+	}
+
+#define UA_TYPE_COPY_AS(TYPE, TYPE_AS)									\
+    UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {					\
+		return TYPE_AS##_copy((TYPE_AS *)src, (TYPE_AS *)dst);			\
+	}
+
+#define UA_TYPE_AS(TYPE, TYPE_AS)			\
+	UA_TYPE_NEW_DEFAULT(TYPE)				\
+	UA_TYPE_INIT_AS(TYPE, TYPE_AS)			\
+	UA_TYPE_DELETE_AS(TYPE, TYPE_AS)		\
+	UA_TYPE_DELETEMEMBERS_AS(TYPE, TYPE_AS)	\
+	UA_TYPE_COPY_AS(TYPE, TYPE_AS)
+
+#endif /* UA_TYPES_H_ */

+ 880 - 0
src/ua_types_encoding_binary.c

@@ -0,0 +1,880 @@
+#include "ua_types_encoding_binary.h"
+#include "ua_namespace_0.h"
+
+/*********/
+/* 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;
+	for(UA_Int32 i = 0;i < nElements;i++) {
+		length += UA_.types[type].encodings[0].calcSize(cdata);
+		cdata += UA_.types[type].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;
+	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;
+	}
+	return retval;
+}
+
+UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_Int32 noElements, UA_Int32 type, void **dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_Array_new(dst, noElements, type);
+
+	UA_Byte *arr    = (UA_Byte *) *dst;
+	UA_Int32 i      = 0;
+	for(;i < noElements && retval == UA_SUCCESS;i++) {
+		retval |= UA_.types[type].encodings[0].decode((void *)src, offset, arr);
+		arr += UA_.types[type].memSize;
+	}
+
+	/* If dynamically sized elements have already been decoded into the array. */
+	if(retval != UA_SUCCESS)
+		UA_Array_delete(dst, i, type);
+
+	return retval;
+}
+
+/************/
+/* Built-In */
+/************/
+
+#define UA_TYPE_CALCSIZEBINARY_SIZEOF(TYPE)							\
+	UA_Int32 TYPE##_calcSizeBinary(TYPE const * p) { return sizeof(TYPE); }
+
+#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(*offset < 0 || (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)                                                \
+    UA_Int32 TYPE##_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, TYPE * dst) { \
+		UA_Int32 retval = UA_SUCCESS;                                                   \
+		if( *offset< 0 || (UA_Int32) (*offset + TYPE##_calcSizeBinary(UA_NULL)) > src->length ) { \
+			return UA_ERR_INVALID_VALUE;                                                \
+		} else {                                                                        \
+			CODE                                                                        \
+		}                                                                               \
+		return retval;                                                                  \
+	}
+
+/* Boolean */
+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; )
+
+/* SByte */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_SByte)
+UA_TYPE_ENCODEBINARY(UA_SByte, dst->data[(*offset)++] = *src; )
+UA_TYPE_DECODEBINARY(UA_SByte, *dst = src->data[(*offset)++]; )
+
+/* Byte */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Byte)
+UA_TYPE_ENCODEBINARY(UA_Byte, dst->data[(*offset)++] = *src; )
+UA_TYPE_DECODEBINARY(UA_Byte, *dst = src->data[(*offset)++]; )
+
+/* Int16 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int16)
+UA_TYPE_ENCODEBINARY(UA_Int16, retval = UA_UInt16_encodeBinary((UA_UInt16 const *)src, dst, offset); )
+UA_TYPE_DECODEBINARY(UA_Int16,
+                     *dst  = (UA_Int16)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 0);
+                     *dst |= (UA_Int16)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 8); )
+
+/* UInt16 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt16)
+UA_TYPE_ENCODEBINARY(UA_UInt16,
+                     dst->data[(*offset)++] = (*src & 0x00FF) >> 0;
+                     dst->data[(*offset)++] = (*src & 0xFF00) >> 8; )
+UA_TYPE_DECODEBINARY(UA_UInt16,
+                     *dst =  (UA_UInt16)src->data[(*offset)++] << 0;
+                     *dst |= (UA_UInt16)src->data[(*offset)++] << 8; )
+
+/* Int32 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int32)
+UA_TYPE_ENCODEBINARY(UA_Int32,
+                     dst->data[(*offset)++] = (*src & 0x000000FF) >> 0;
+                     dst->data[(*offset)++] = (*src & 0x0000FF00) >> 8;
+                     dst->data[(*offset)++] = (*src & 0x00FF0000) >> 16;
+                     dst->data[(*offset)++] = (*src & 0xFF000000) >> 24; )
+UA_TYPE_DECODEBINARY(UA_Int32,
+                     *dst  = (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 0);
+                     *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 8);
+                     *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 16);
+                     *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 24); )
+
+/* UInt32 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt32)
+UA_TYPE_ENCODEBINARY(UA_UInt32, retval = UA_Int32_encodeBinary((UA_Int32 const *)src, dst, offset); )
+UA_TYPE_DECODEBINARY(UA_UInt32,
+                     UA_UInt32 t1 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++] & 0xFF));
+                     UA_UInt32 t2 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 8);
+                     UA_UInt32 t3 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 16);
+                     UA_UInt32 t4 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 24);
+                     *dst = t1 + t2 + t3 + t4; )
+
+/* Int64 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int64)
+UA_TYPE_ENCODEBINARY(UA_Int64,
+                     dst->data[(*offset)++] = (*src & 0x00000000000000FF) >> 0;
+                     dst->data[(*offset)++] = (*src & 0x000000000000FF00) >> 8;
+                     dst->data[(*offset)++] = (*src & 0x0000000000FF0000) >> 16;
+                     dst->data[(*offset)++] = (*src & 0x00000000FF000000) >> 24;
+                     dst->data[(*offset)++] = (*src & 0x000000FF00000000) >> 32;
+                     dst->data[(*offset)++] = (*src & 0x0000FF0000000000) >> 40;
+                     dst->data[(*offset)++] = (*src & 0x00FF000000000000) >> 48;
+                     dst->data[(*offset)++] = (*src & 0xFF00000000000000) >> 56; )
+UA_TYPE_DECODEBINARY(UA_Int64,
+                     *dst  = (UA_Int64)src->data[(*offset)++] << 0;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 8;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 16;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 24;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 32;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 40;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 48;
+                     *dst |= (UA_Int64)src->data[(*offset)++] << 56; )
+
+/* UInt64 */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt64)
+UA_TYPE_ENCODEBINARY(UA_UInt64, return UA_Int64_encodeBinary((UA_Int64 const *)src, dst, offset); )
+UA_TYPE_DECODEBINARY(UA_UInt64,
+                     UA_UInt64 t1 = (UA_UInt64)src->data[(*offset)++];
+                     UA_UInt64 t2 = (UA_UInt64)src->data[(*offset)++] << 8;
+                     UA_UInt64 t3 = (UA_UInt64)src->data[(*offset)++] << 16;
+                     UA_UInt64 t4 = (UA_UInt64)src->data[(*offset)++] << 24;
+                     UA_UInt64 t5 = (UA_UInt64)src->data[(*offset)++] << 32;
+                     UA_UInt64 t6 = (UA_UInt64)src->data[(*offset)++] << 40;
+                     UA_UInt64 t7 = (UA_UInt64)src->data[(*offset)++] << 48;
+                     UA_UInt64 t8 = (UA_UInt64)src->data[(*offset)++] << 56;
+                     *dst = t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8; )
+
+/* Float */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Float)
+// FIXME: Implement NaN, Inf and Zero(s)
+UA_Byte UA_FLOAT_ZERO[] = { 0x00, 0x00, 0x00, 0x00 };
+UA_TYPE_DECODEBINARY(UA_Float,
+                     if(memcmp(&src->data[*offset], UA_FLOAT_ZERO,
+                               4) == 0) return UA_Int32_decodeBinary(src, offset, (UA_Int32 *)dst); UA_Float mantissa;
+                     mantissa = (UA_Float)(src->data[*offset] & 0xFF);                         // bits 0-7
+                     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
+                     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; )
+UA_TYPE_ENCODEBINARY(UA_Float, return UA_UInt32_encodeBinary((UA_UInt32 *)src, dst, offset); )
+
+/* Double */
+UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Double)
+// FIXME: Implement NaN, Inf and Zero(s)
+UA_Byte UA_DOUBLE_ZERO[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+UA_TYPE_DECODEBINARY(UA_Double,
+                     if(memcmp(&src->data[*offset], UA_DOUBLE_ZERO,
+                               8) == 0) return UA_Int64_decodeBinary(src, offset, (UA_Int64 *)dst); UA_Double mantissa;
+                     mantissa = (UA_Double)(src->data[*offset] & 0xFF);                         // bits 0-7
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+1] & 0xFF); // bits 8-15
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+2] & 0xFF); // bits 16-23
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+3] & 0xFF); // bits 24-31
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+4] & 0xFF); // bits 32-39
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+5] & 0xFF); // bits 40-47
+                     mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+6] & 0x0F); // bits 48-51
+                     DBG_VERBOSE(printf("UA_Double_decodeBinary - mantissa=%f\n", mantissa));
+                     UA_UInt32 biasedExponent;
+                     biasedExponent  = (src->data[*offset+6] & 0xF0) >>  4; // bits 52-55
+                     DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent52-55=%d, src=%d\n", biasedExponent,
+                                        src->data[*offset+6]));
+                     biasedExponent |= ((UA_UInt32)(src->data[*offset+7] & 0x7F)) <<  4; // bits 56-62
+                     DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent56-62=%d, src=%d\n", biasedExponent,
+                                        src->data[*offset+7]));
+                     UA_Double sign = ( src->data[*offset+7] & 0x80 ) ? -1.0 : 1.0; // bit 63
+                     if(biasedExponent >= 1023)
+						 *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; )
+UA_TYPE_ENCODEBINARY(UA_Double, return UA_UInt64_encodeBinary((UA_UInt64 *)src, dst, offset); )
+
+/* String */
+UA_Int32 UA_String_calcSizeBinary(UA_String const *string) {
+	if(string == UA_NULL) // internal size for UA_memalloc
+		return sizeof(UA_String);
+	else {                // binary encoding size
+		if(string->length > 0)
+			return sizeof(UA_Int32) + string->length * sizeof(UA_Byte);
+		else
+			return sizeof(UA_Int32);
+	}
+}
+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;
+	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;
+	}
+	return retval;
+}
+UA_Int32 UA_String_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_String *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_String_init(dst);
+	retval |= UA_Int32_decodeBinary(src, offset, &dst->length);
+	if(dst->length > (UA_Int32)(src->length - *offset))
+		retval = UA_ERR_INVALID_VALUE;
+	if(retval != UA_SUCCESS || dst->length <= 0) {
+		dst->length = -1;
+		dst->data   = UA_NULL;
+	} else {
+		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;
+	}
+	return retval;
+}
+
+/* DateTime */
+UA_TYPE_ENCODEBINARY_AS(UA_DateTime, UA_Int64)
+UA_TYPE_DECODEBINARY_AS(UA_DateTime, UA_Int64)
+
+/* Guid */
+UA_Int32 UA_Guid_calcSizeBinary(UA_Guid const *p) {
+	if(p == UA_NULL)
+		return sizeof(UA_Guid);
+	else
+		return 16;
+}
+
+UA_TYPE_ENCODEBINARY(UA_Guid,
+                     CHECKED_DECODE(UA_UInt32_encodeBinary(&src->data1, dst, offset),; );
+                     CHECKED_DECODE(UA_UInt16_encodeBinary(&src->data2, dst, offset),; );
+                     CHECKED_DECODE(UA_UInt16_encodeBinary(&src->data3, dst, offset),; );
+                     for(UA_Int32 i = 0;i < 8;i++)
+						 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++)
+						 CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->data4[i]),; ); )
+
+/* ByteString */
+UA_TYPE_ENCODEBINARY_AS(UA_ByteString, UA_String)
+UA_TYPE_DECODEBINARY_AS(UA_ByteString, UA_String)
+
+/* XmlElement */
+UA_TYPE_ENCODEBINARY_AS(UA_XmlElement, UA_String)
+UA_TYPE_DECODEBINARY_AS(UA_XmlElement, UA_String)
+
+/* NodeId */
+UA_Int32 UA_NodeId_calcSizeBinary(UA_NodeId const *p) {
+	UA_Int32 length = 0;
+	if(p == UA_NULL)
+		length = sizeof(UA_NodeId);
+	else {
+		switch(p->encodingByte & UA_NODEIDTYPE_MASK) {
+		case UA_NODEIDTYPE_TWOBYTE:
+			length = 2;
+			break;
+
+		case UA_NODEIDTYPE_FOURBYTE:
+			length = 4;
+			break;
+
+		case UA_NODEIDTYPE_NUMERIC:
+			length += sizeof(UA_Byte) + sizeof(UA_UInt16) + sizeof(UA_UInt32);
+			break;
+
+		case UA_NODEIDTYPE_STRING:
+			length += sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_String_calcSizeBinary(&p->identifier.string);
+			break;
+
+		case UA_NODEIDTYPE_GUID:
+			length += sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_Guid_calcSizeBinary(&p->identifier.guid);
+			break;
+
+		case UA_NODEIDTYPE_BYTESTRING:
+			length += sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_ByteString_calcSizeBinary(&p->identifier.byteString);
+			break;
+
+		default:
+			break;
+		}
+	}
+	return length;
+}
+
+UA_TYPE_ENCODEBINARY(UA_NodeId,
+                     // temporary variables for endian-save code
+                     UA_Byte srcByte;
+                     UA_UInt16 srcUInt16;
+
+                     UA_Int32 retval = UA_SUCCESS;
+                     retval |= UA_Byte_encodeBinary(&src->encodingByte, dst, offset);
+                     switch(src->encodingByte & UA_NODEIDTYPE_MASK) {
+					 case UA_NODEIDTYPE_TWOBYTE:
+						 srcByte = src->identifier.numeric;
+						 retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
+						 break;
+
+					 case UA_NODEIDTYPE_FOURBYTE:
+						 srcByte = src->namespace;
+						 srcUInt16 = src->identifier.numeric;
+						 retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
+						 retval |= UA_UInt16_encodeBinary(&srcUInt16, dst, offset);
+						 break;
+
+					 case UA_NODEIDTYPE_NUMERIC:
+						 retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
+						 retval |= UA_UInt32_encodeBinary(&src->identifier.numeric, dst, offset);
+						 break;
+
+					 case UA_NODEIDTYPE_STRING:
+						 retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
+						 retval |= UA_String_encodeBinary(&src->identifier.string, dst, offset);
+						 break;
+
+					 case UA_NODEIDTYPE_GUID:
+						 retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
+						 retval |= UA_Guid_encodeBinary(&src->identifier.guid, dst, offset);
+						 break;
+
+					 case UA_NODEIDTYPE_BYTESTRING:
+						 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_NodeId_init(dst);
+	// temporary variables to overcome decoder's non-endian-saveness for datatypes with different length
+	UA_Byte   dstByte   = 0;
+	UA_UInt16 dstUInt16 = 0;
+
+	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingByte),; );
+	switch(dst->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE: // Table 7
+		CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
+		dst->identifier.numeric = dstByte;
+		dst->namespace = 0; // default namespace
+		break;
+
+	case UA_NODEIDTYPE_FOURBYTE: // Table 8
+		CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
+		dst->namespace = dstByte;
+		CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dstUInt16),; );
+		dst->identifier.numeric = dstUInt16;
+		break;
+
+	case UA_NODEIDTYPE_NUMERIC: // Table 6, first entry
+		CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
+		CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->identifier.numeric),; );
+		break;
+
+	case UA_NODEIDTYPE_STRING: // Table 6, second entry
+		CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
+		CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->identifier.string),; );
+		break;
+
+	case UA_NODEIDTYPE_GUID: // Table 6, third entry
+		CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
+		CHECKED_DECODE(UA_Guid_decodeBinary(src, offset, &dst->identifier.guid),; );
+		break;
+
+	case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
+		CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
+		CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->identifier.byteString),; );
+		break;
+	}
+	return retval;
+}
+
+/* ExpandedNodeId */
+UA_Int32 UA_ExpandedNodeId_calcSizeBinary(UA_ExpandedNodeId const *p) {
+	UA_Int32 length = 0;
+	if(p == UA_NULL)
+		length = sizeof(UA_ExpandedNodeId);
+	else {
+		length = UA_NodeId_calcSizeBinary(&p->nodeId);
+		if(p->nodeId.encodingByte & UA_NODEIDTYPE_NAMESPACE_URI_FLAG)
+			length += UA_String_calcSizeBinary(&p->namespaceUri); //p->namespaceUri
+		if(p->nodeId.encodingByte & UA_NODEIDTYPE_SERVERINDEX_FLAG)
+			length += sizeof(UA_UInt32);                    //p->serverIndex
+	}
+	return length;
+}
+
+UA_String UA_String_null = { -1, UA_NULL };
+UA_TYPE_ENCODEBINARY(UA_ExpandedNodeId,
+                     retval |= UA_NodeId_encodeBinary(&src->nodeId, dst, offset);
+                     if(src->nodeId.encodingByte & UA_NODEIDTYPE_NAMESPACE_URI_FLAG)
+						 retval |= UA_String_encodeBinary(&src->namespaceUri, dst, offset);
+                     if(src->nodeId.encodingByte & UA_NODEIDTYPE_SERVERINDEX_FLAG)
+						 retval |= UA_UInt32_encodeBinary(&src->serverIndex, dst, offset);
+                     )
+UA_Int32 UA_ExpandedNodeId_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_ExpandedNodeId *dst) {
+	UA_UInt32 retval = UA_SUCCESS;
+	UA_ExpandedNodeId_init(dst);
+	CHECKED_DECODE(UA_NodeId_decodeBinary(src, offset, &dst->nodeId), UA_ExpandedNodeId_deleteMembers(dst));
+	if(dst->nodeId.encodingByte & UA_NODEIDTYPE_NAMESPACE_URI_FLAG) {
+		dst->nodeId.namespace = 0;
+		CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->namespaceUri), UA_ExpandedNodeId_deleteMembers(dst));
+	} else {
+	CHECKED_DECODE(UA_String_copy(&UA_String_null, &dst->namespaceUri), UA_ExpandedNodeId_deleteMembers(dst));
+	}
+
+	if(dst->nodeId.encodingByte & UA_NODEIDTYPE_SERVERINDEX_FLAG)
+		CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->serverIndex), UA_ExpandedNodeId_deleteMembers(dst));
+	return retval;
+}
+
+/* StatusCode */
+
+/* QualifiedName */
+UA_Int32 UA_QualifiedName_calcSizeBinary(UA_QualifiedName const *p) {
+	UA_Int32 length = 0;
+	if(p == UA_NULL) return sizeof(UA_QualifiedName);
+	length += sizeof(UA_UInt16);              //qualifiedName->namespaceIndex
+	// length += sizeof(UA_UInt16); //qualifiedName->reserved
+	length += UA_String_calcSizeBinary(&p->name); //qualifiedName->name
+	return length;
+}
+UA_Int32 UA_QualifiedName_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_QualifiedName *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_QualifiedName_init(dst);
+	CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
+	CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->name),; );
+	return retval;
+}
+UA_TYPE_ENCODEBINARY(UA_QualifiedName,
+                     retval |= UA_UInt16_encodeBinary(&src->namespaceIndex, dst, offset);
+                     retval |= UA_String_encodeBinary(&src->name, dst, offset); )
+
+/* LocalizedText */
+UA_Int32 UA_LocalizedText_calcSizeBinary(UA_LocalizedText const *p) {
+	UA_Int32 length = 0;
+	if(p == UA_NULL) {
+		// size for UA_memalloc
+		length = sizeof(UA_LocalizedText);
+	} else {
+		// size for binary encoding
+		length += 1; // p->encodingMask;
+		if(p->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
+			length += UA_String_calcSizeBinary(&p->locale);
+		if(p->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
+			length += UA_String_calcSizeBinary(&p->text);
+	}
+	return length;
+}
+
+UA_TYPE_ENCODEBINARY(UA_LocalizedText,
+                     retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
+                     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);)
+
+UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_LocalizedText *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+
+	retval |= UA_String_init(&dst->locale);
+	retval |= UA_String_init(&dst->text);
+
+	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingMask),; );
+	if(dst->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
+		CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->locale), UA_LocalizedText_deleteMembers(dst));
+	if(dst->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
+		CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->text), UA_LocalizedText_deleteMembers(dst));
+	return retval;
+}
+
+/* ExtensionObject */
+UA_Int32 UA_ExtensionObject_calcSizeBinary(UA_ExtensionObject const *p) {
+	UA_Int32 length = 0;
+	if(p == UA_NULL)
+		length = sizeof(UA_ExtensionObject);
+	else {
+		length += UA_NodeId_calcSizeBinary(&p->typeId);
+		length += 1; //p->encoding
+		switch(p->encoding) {
+		case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
+			length += UA_ByteString_calcSizeBinary(&p->body);
+			break;
+
+		case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
+			length += UA_XmlElement_calcSizeBinary((UA_XmlElement *)&p->body);
+			break;
+		}
+	}
+	return length;
+}
+
+UA_TYPE_ENCODEBINARY(UA_ExtensionObject,
+                     retval |= UA_NodeId_encodeBinary(&src->typeId, dst, offset);
+                     retval |= UA_Byte_encodeBinary(&src->encoding, dst, offset);
+                     switch(src->encoding) {
+					 case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
+						 break;
+
+					 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);
+						 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;
+	UA_ExtensionObject_init(dst);
+	CHECKED_DECODE(UA_NodeId_decodeBinary(src, offset, &dst->typeId), UA_ExtensionObject_deleteMembers(dst));
+	CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encoding), UA_ExtensionObject_deleteMembers(dst));
+	CHECKED_DECODE(UA_String_copy(&UA_String_null, (UA_String *)&dst->body), UA_ExtensionObject_deleteMembers(dst));
+	switch(dst->encoding) {
+	case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
+		break;
+
+	case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
+	case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
+		CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->body), UA_ExtensionObject_deleteMembers(dst));
+		break;
+	}
+	return retval;
+}
+
+/* DataValue */
+//TODO: place this define at the server configuration
+#define MAX_PICO_SECONDS 1000
+UA_Int32 UA_DataValue_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_DataValue *dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_DataValue_init(dst);
+	retval |= UA_Byte_decodeBinary(src, offset, &dst->encodingMask);
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
+		CHECKED_DECODE(UA_Variant_decodeBinary(src, offset, &dst->value), UA_DataValue_deleteMembers(dst));
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
+		CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->status), UA_DataValue_deleteMembers(dst));
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
+		CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->sourceTimestamp), UA_DataValue_deleteMembers(dst));
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS) {
+		CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->sourcePicoseconds), UA_DataValue_deleteMembers(dst));
+		if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
+			dst->sourcePicoseconds = MAX_PICO_SECONDS;
+	}
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
+		CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->serverTimestamp), UA_DataValue_deleteMembers(dst));
+	if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS) {
+		CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->serverPicoseconds), UA_DataValue_deleteMembers(dst));
+		if(dst->serverPicoseconds > MAX_PICO_SECONDS)
+			dst->serverPicoseconds = MAX_PICO_SECONDS;
+	}
+	return retval;
+}
+
+UA_TYPE_ENCODEBINARY(UA_DataValue,
+                     retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
+						 retval |= UA_Variant_encodeBinary(&src->value, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
+						 retval |= UA_StatusCode_encodeBinary(&src->status, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
+						 retval |= UA_DateTime_encodeBinary(&src->sourceTimestamp, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
+						 retval |= UA_Int16_encodeBinary(&src->sourcePicoseconds, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
+						 retval |= UA_DateTime_encodeBinary(&src->serverTimestamp, dst, offset);
+                     if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
+						 retval |= UA_Int16_encodeBinary(&src->serverPicoseconds, dst, offset);
+                     )
+
+UA_Int32 UA_DataValue_calcSizeBinary(UA_DataValue const *p) {
+	UA_Int32 length = 0;
+
+	if(p == UA_NULL) // get static storage size
+		length = sizeof(UA_DataValue);
+	else {           // get decoding size
+		length = sizeof(UA_Byte);
+		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT) {
+			// FIXME: this one can return with an error value instead of a size
+			length += UA_Variant_calcSizeBinary(&p->value);
+		}
+		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
+		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
+		if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
+			length += sizeof(UA_Int64);    //dataValue->serverPicoseconds
+	}
+	return length;
+}
+
+/* Variant */
+UA_Int32 UA_Variant_calcSizeBinary(UA_Variant const *p) {
+	UA_Int32   length        = 0;
+	if(p == UA_NULL) return sizeof(UA_Variant);
+	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 || builtinNs0Id != p->vt->typeId.namespace) return UA_ERR_INCONSISTENT;
+	length += sizeof(UA_Byte);      //p->encodingMask
+	if(isArray) {                   // array length is encoded
+		length += sizeof(UA_Int32); //p->arrayLength
+		if(p->arrayLength > 0) {
+			// TODO: add suggestions of @jfpr to not iterate over arrays with fixed len elements
+			// FIXME: the concept of calcSizeBinary delivering the storageSize given an UA_Null argument
+			// fails for arrays with null-ptrs, see test case
+			// UA_Variant_calcSizeBinaryVariableSizeArrayWithNullPtrWillReturnWrongEncodingSize
+			// Simply do not allow?
+			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
+	}
+	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;
+
+                     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);
+						 }
+					 }
+
+                     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_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
+		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_new(&dst->data, dst->arrayLength, uaIdx), dst->data = UA_NULL);
+		CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, uaIdx, &dst->data), UA_Variant_deleteMembers(dst));
+	}
+	//decode the dimension field array if present
+	if(dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+		UA_Int32_decodeBinary(src, offset, &dst->arrayDimensionsLength);
+		CHECKED_DECODE(UA_Array_new((void **)&dst->arrayDimensions, dst->arrayDimensionsLength, UA_INT32), dst->arrayDimensions = UA_NULL);
+		CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, uaIdx,
+		                                     &dst->data), UA_Variant_deleteMembers(dst));
+	}
+	return retval;
+}
+
+/* DiagnosticInfo */
+UA_Int32 UA_DiagnosticInfo_calcSizeBinary(UA_DiagnosticInfo const *ptr) {
+	UA_Int32 length = 0;
+	if(ptr == UA_NULL)
+		length = sizeof(UA_DiagnosticInfo);
+	else {
+		UA_Byte mask;
+		length += sizeof(UA_Byte);  // EncodingMask
+
+		for(mask = 0x01;mask <= 0x40;mask *= 2) {
+			switch(mask & (ptr->encodingMask)) {
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
+				//	puts("diagnosticInfo symbolic id");
+				length += sizeof(UA_Int32);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
+				length += sizeof(UA_Int32);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
+				length += sizeof(UA_Int32);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
+				length += sizeof(UA_Int32);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
+				length += UA_String_calcSizeBinary(&ptr->additionalInfo);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
+				length += sizeof(UA_StatusCode);
+				break;
+
+			case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
+				length += UA_DiagnosticInfo_calcSizeBinary(ptr->innerDiagnosticInfo);
+				break;
+			}
+		}
+	}
+	return length;
+}
+
+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),; );
+
+	for(UA_Int32 i = 0;i < 7;i++) {
+		switch( (0x01 << i) & dst->encodingMask) {
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
+			CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->symbolicId),; );
+			break;
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
+			CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->namespaceUri),; );
+			break;
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
+			CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->localizedText),; );
+			break;
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
+			CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->locale),; );
+			break;
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
+			CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->additionalInfo),; );
+			break;
+
+		case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
+			CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->innerStatusCode),; );
+			break;
+
+		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_DiagnosticInfo_decodeBinary(src, offset,
+			                                              dst->innerDiagnosticInfo),
+			               UA_DiagnosticInfo_deleteMembers(dst));
+			break;
+		}
+	}
+	return retval;
+}
+
+UA_TYPE_ENCODEBINARY(UA_DiagnosticInfo,
+                     retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
+                     for(UA_Int32 i = 0;i < 7;i++) {
+                         switch( (0x01 << i) & src->encodingMask) {
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
+							 retval |= UA_Int32_encodeBinary(&src->symbolicId, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
+							 retval |=  UA_Int32_encodeBinary( &src->namespaceUri, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
+							 retval |= UA_Int32_encodeBinary(&src->localizedText, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
+							 retval |= UA_Int32_encodeBinary(&src->locale, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
+							 retval |= UA_String_encodeBinary(&src->additionalInfo, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
+							 retval |= UA_StatusCode_encodeBinary(&src->innerStatusCode, dst, offset);
+							 break;
+
+						 case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
+							 retval |= UA_DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, dst, offset);
+							 break;
+						 }
+					 })
+
+/* InvalidType */
+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; )

+ 79 - 0
src/ua_types_encoding_binary.h

@@ -0,0 +1,79 @@
+#ifndef UA_TYPES_ENCODING_BINARY_H_
+#define UA_TYPES_ENCODING_BINARY_H_
+
+#include "ua_util.h"
+#include "ua_types.h"
+
+/* Stop decoding at the first failure. Free members that were already allocated.
+   It is assumed that retval is already defined. */
+#define CHECKED_DECODE(DECODE, CLEAN_UP) do { \
+		retval |= DECODE;												\
+		if(retval != UA_SUCCESS) {										\
+			CLEAN_UP;													\
+			return retval;												\
+		} } while(0)													
+
+#define UA_TYPE_BINARY_ENCODING_AS(TYPE, TYPE_AS)						\
+	UA_TYPE_CALCSIZEBINARY_AS(TYPE, TYPE_AS)									\
+	UA_TYPE_ENCODEBINARY_AS(TYPE,TYPE_AS)								\
+	UA_TYPE_DECODEBINARY_AS(TYPE, TYPE_AS)
+
+#define UA_TYPE_CALCSIZEBINARY_AS(TYPE, TYPE_AS)						\
+	UA_Int32 TYPE##_calcSizeBinary(TYPE const * p) { return TYPE_AS##_calcSizeBinary((TYPE_AS*) p); }
+
+#define UA_TYPE_ENCODEBINARY_AS(TYPE,TYPE_AS)					\
+	UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_ByteString *dst, UA_UInt32 *offset) { \
+		return TYPE_AS##_encodeBinary((TYPE_AS*)src, dst, offset);				\
+	}
+
+#define UA_TYPE_DECODEBINARY_AS(TYPE, TYPE_AS)                                  \
+	UA_Int32 TYPE##_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst) { \
+		return TYPE_AS##_decodeBinary(src, offset, (TYPE_AS*)dst); \
+	}
+
+#define UA_TYPE_BINARY_ENCODING(TYPE)									\
+	UA_Int32 TYPE##_calcSizeBinary(TYPE const * p);							\
+	UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_ByteString *dst, UA_UInt32 *offset); \
+	UA_Int32 TYPE##_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, TYPE *dst);
+
+UA_TYPE_BINARY_ENCODING(UA_Boolean)
+UA_TYPE_BINARY_ENCODING(UA_SByte)
+UA_TYPE_BINARY_ENCODING(UA_Byte)
+UA_TYPE_BINARY_ENCODING(UA_Int16)
+UA_TYPE_BINARY_ENCODING(UA_UInt16)
+UA_TYPE_BINARY_ENCODING(UA_Int32)
+UA_TYPE_BINARY_ENCODING(UA_UInt32)
+UA_TYPE_BINARY_ENCODING(UA_Int64)
+UA_TYPE_BINARY_ENCODING(UA_UInt64)
+UA_TYPE_BINARY_ENCODING(UA_Float)
+UA_TYPE_BINARY_ENCODING(UA_Double)
+UA_TYPE_BINARY_ENCODING(UA_String)
+UA_TYPE_BINARY_ENCODING(UA_DateTime)
+UA_TYPE_BINARY_ENCODING(UA_Guid)
+UA_TYPE_BINARY_ENCODING(UA_ByteString)
+UA_TYPE_BINARY_ENCODING(UA_XmlElement)
+UA_TYPE_BINARY_ENCODING(UA_NodeId)
+UA_TYPE_BINARY_ENCODING(UA_ExpandedNodeId)
+UA_TYPE_BINARY_ENCODING(UA_StatusCode)
+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_TYPE_BINARY_ENCODING(UA_InvalidType)
+
+/*********/
+/* Array */
+/*********/
+
+/* 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);
+
+/* @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);
+
+/* @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);
+
+#endif /* UA_TYPES_ENCODING_BINARY_H_ */

+ 153 - 0
src/ua_types_encoding_xml.c

@@ -0,0 +1,153 @@
+#include "ua_types_encoding_xml.h"
+#include "ua_util.h"
+#include "ua_xml.h"
+
+/* Boolean */
+
+UA_Int32 UA_Boolean_copycstring(cstring src, UA_Boolean *dst) {
+	*dst = UA_FALSE;
+	if(0 == strncmp(src, "true", 4) || 0 == strncmp(src, "TRUE", 4))
+		*dst = UA_TRUE;
+	return UA_SUCCESS;
+}
+
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Boolean)
+UA_Int32 UA_Boolean_decodeXML(XML_Stack *s, XML_Attr *attr, UA_Boolean *dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_Boolean entered with dst=%p,isStart=%d\n", (void * )dst, isStart));
+	if(isStart) {
+		if(dst == UA_NULL) {
+			UA_Boolean_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void *)dst;
+		}
+		UA_Boolean_copycstring((cstring)attr[1], dst);
+	}
+	return UA_SUCCESS;
+}
+
+/* SByte */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_SByte)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_SByte)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_SByte)
+
+/* Byte */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Byte)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Byte)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Byte)
+
+/* Int16 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Int16)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Int16)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Int16)
+
+/* UInt16 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_UInt16)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_UInt16)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_UInt16)
+
+/* Int32 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Int32)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Int32)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Int32)
+
+/* UInt32 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_UInt32)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_UInt32)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_UInt32)
+
+/* Int64 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Int64)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Int64)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Int64)
+
+/* UInt64 */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_UInt64)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_UInt64)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_UInt64)
+
+/* Float */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Float)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Float)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Float)
+
+/* Double */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Double)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Double)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Double)
+
+/* String */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_String)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_String)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_String)
+
+/* DateTime */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DateTime)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_DateTime)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_DateTime)
+
+/* Guid */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Guid)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Guid)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Guid)
+
+/* ByteString */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ByteString)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ByteString)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ByteString)
+
+/* XmlElement */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_XmlElement)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_XmlElement)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_XmlElement)
+
+/* NodeId */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_NodeId)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_NodeId)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_NodeId)
+
+/* ExpandedNodeId */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ExpandedNodeId)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ExpandedNodeId)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ExpandedNodeId)
+
+/* StatusCode */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_StatusCode)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_StatusCode)
+UA_Int32 UA_StatusCode_decodeXML(XML_Stack *s, XML_Attr *attr, UA_StatusCode *dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_StatusCode_decodeXML entered with dst=%p,isStart=%d\n", (void * )dst, isStart));
+	return UA_ERR_NOT_IMPLEMENTED;
+}
+
+/* QualifiedName */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_QualifiedName)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_QualifiedName)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_QualifiedName)
+
+/* LocalizedText */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_LocalizedText)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_LocalizedText)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_LocalizedText)
+
+/* ExtensionObject */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ExtensionObject)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ExtensionObject)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ExtensionObject)
+
+/* DataValue */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DataValue)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_DataValue)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_DataValue)
+
+/* Variant */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Variant)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_Variant)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_Variant)
+
+/* DiagnosticInfo */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DiagnosticInfo)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_DiagnosticInfo)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_DiagnosticInfo)
+
+/* InvalidType */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_InvalidType)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_InvalidType)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_InvalidType)

+ 65 - 0
src/ua_types_encoding_xml.h

@@ -0,0 +1,65 @@
+#ifndef UA_TYPES_ENCODING_XML_H_
+#define UA_TYPES_ENCODING_XML_H_
+
+#include "ua_xml.h"
+#include "ua_types.h"
+
+#define UA_TYPE_XML_ENCODING(TYPE)							\
+	UA_Int32 TYPE##_calcSizeXml(const void * p); \
+    UA_Int32 TYPE##_encodeXml(const TYPE *src, UA_ByteString *dst, UA_UInt32 *offset); \
+	UA_Int32 TYPE##_decodeXml(UA_ByteString *src, UA_UInt32 *offset, TYPE *dst); \
+	UA_Int32 TYPE##_encodeXmlToStack(const TYPE *src, XML_Stack *s, XML_Attr *attr); \
+	UA_Int32 TYPE##_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, TYPE* dst, UA_Boolean isStart);
+
+#define UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(TYPE) \
+	UA_Int32 TYPE##_calcSizeXml(const void * p) { \
+	return -1; \
+ }
+
+#define UA_TYPE_METHOD_ENCODEXML_NOTIMPL(TYPE) \
+    UA_Int32 TYPE##_encodeXml(const TYPE *src, UA_ByteString *dst, UA_UInt32 *offset) { \
+        return UA_ERR_NOT_IMPLEMENTED; \
+	}																	\
+	UA_Int32 TYPE##_encodeXmlToStack(const TYPE *src, XML_Stack *s, XML_Attr *attr) { \
+     DBG_VERBOSE(printf(#TYPE "_encodeXML entered with src=%p,isStart=%d\n", (void* ) src)); \
+     return UA_ERR_NOT_IMPLEMENTED;\
+ }
+
+#define UA_TYPE_METHOD_DECODEXML_NOTIMPL(TYPE) \
+	UA_Int32 TYPE##_decodeXml(UA_ByteString *src, UA_UInt32 *offset, TYPE *dst) { \
+        return UA_ERR_NOT_IMPLEMENTED;									\
+	}																	\
+ UA_Int32 TYPE##_decodeXMLFromStack(XML_Stack* s, XML_Attr* attr, TYPE* dst, UA_Boolean isStart) { \
+     DBG_VERBOSE(printf(#TYPE "_decodeXML entered with dst=%p,isStart=%d\n", (void* ) dst, isStart)); \
+     return UA_ERR_NOT_IMPLEMENTED;\
+ }
+
+
+UA_TYPE_XML_ENCODING(UA_Boolean)
+UA_TYPE_XML_ENCODING(UA_SByte)
+UA_TYPE_XML_ENCODING(UA_Byte)
+UA_TYPE_XML_ENCODING(UA_Int16)
+UA_TYPE_XML_ENCODING(UA_UInt16)
+UA_TYPE_XML_ENCODING(UA_Int32)
+UA_TYPE_XML_ENCODING(UA_UInt32)
+UA_TYPE_XML_ENCODING(UA_Int64)
+UA_TYPE_XML_ENCODING(UA_UInt64)
+UA_TYPE_XML_ENCODING(UA_Float)
+UA_TYPE_XML_ENCODING(UA_Double)
+UA_TYPE_XML_ENCODING(UA_String)
+UA_TYPE_XML_ENCODING(UA_DateTime)
+UA_TYPE_XML_ENCODING(UA_Guid)
+UA_TYPE_XML_ENCODING(UA_ByteString)
+UA_TYPE_XML_ENCODING(UA_XmlElement)
+UA_TYPE_XML_ENCODING(UA_NodeId)
+UA_TYPE_XML_ENCODING(UA_ExpandedNodeId)
+UA_TYPE_XML_ENCODING(UA_StatusCode)
+UA_TYPE_XML_ENCODING(UA_QualifiedName)
+UA_TYPE_XML_ENCODING(UA_LocalizedText)
+UA_TYPE_XML_ENCODING(UA_ExtensionObject)
+UA_TYPE_XML_ENCODING(UA_DataValue)
+UA_TYPE_XML_ENCODING(UA_Variant)
+UA_TYPE_XML_ENCODING(UA_DiagnosticInfo)
+UA_TYPE_XML_ENCODING(UA_InvalidType)
+
+#endif /* UA_TYPES_ENCODING_XML_H_ */

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 15835 - 0
src/ua_types_generated.c


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3028 - 0
src/ua_types_generated.h


+ 60 - 0
src/ua_util.h

@@ -0,0 +1,60 @@
+#ifndef UA_UTILITY_H_
+#define UA_UTILITY_H_
+
+#include <stdlib.h> // malloc, free
+#include <string.h> // memcpy
+#include "ua_types.h"
+
+/* Debug macros */
+#define DBG_VERBOSE(expression) // omit debug code
+#define DBG_ERR(expression)     // omit debug code
+#define DBG(expression)         // omit debug code
+#if defined(DEBUG)              // --enable-debug=(yes|verbose)
+# undef DBG
+# define DBG(expression) expression
+# undef DBG_ERR
+# define DBG_ERR(expression) expression
+# if defined(VERBOSE)   // --enable-debug=verbose
+#  undef DBG_VERBOSE
+#  define DBG_VERBOSE(expression) expression
+# endif
+#endif
+
+
+/* Global Variables */
+extern UA_ByteString UA_ByteString_securityPoliceNone;
+
+/* Heap memory functions */
+#define UA_NULL ((void *)0)
+extern void const *UA_alloc_lastptr;
+#define UA_free(ptr) _UA_free(ptr, # ptr, __FILE__, __LINE__)
+#define UA_alloc(ptr, size) _UA_alloc(ptr, size, # ptr, # size, __FILE__, __LINE__)
+
+inline UA_Int32 _UA_free(void *ptr, char *pname, char *f, UA_Int32 l) {
+	DBG_VERBOSE(printf("UA_free;%p;;%s;;%s;%d\n", ptr, pname, f, l); fflush(stdout));
+	free(ptr); // checks if ptr != NULL in the background
+	return UA_SUCCESS;
+}
+
+inline UA_Int32 _UA_alloc(void **ptr, UA_Int32 size, char *pname, char *sname, char *f, UA_Int32 l) {
+	if(ptr == UA_NULL) return UA_ERR_INVALID_VALUE;
+	UA_alloc_lastptr = *ptr = malloc(size);
+	DBG_VERBOSE(printf("UA_alloc - %p;%d;%s;%s;%s;%d\n", *ptr, size, pname, sname, f, l); fflush(stdout));
+	if(*ptr == UA_NULL) return UA_ERR_NO_MEMORY;
+	return UA_SUCCESS;
+}
+
+inline UA_Int32 UA_memcpy(void *dst, void const *src, UA_Int32 size) {
+	if(dst == UA_NULL) return UA_ERR_INVALID_VALUE;
+	DBG_VERBOSE(printf("UA_memcpy - %p;%p;%d\n", dst, src, size));
+	memcpy(dst, src, size);
+	return UA_SUCCESS;
+}
+
+static inline UA_Int32 UA_VTable_isValidType(UA_Int32 type) {
+	if(type < 0 /* UA_BOOLEAN */ || type > 271 /* UA_INVALID */)
+		return UA_ERR_INVALID_VALUE;
+	return UA_SUCCESS;
+}
+
+#endif /* UA_UTILITY_H_ */

+ 138 - 141
src/ua_xml.c

@@ -1,17 +1,11 @@
-/*
- * ua_xml.c
- *
- *  Created on: 03.05.2014
- *      Author: mrt
- */
-
-#include "ua_xml.h"
+#include "ua_types_generated.h"
+#include "ua_types_encoding_xml.h"
+#include "ua_xml_namespace.h"
 #include <fcntl.h> // open, O_RDONLY
 
-
 UA_Int32 UA_TypedArray_init(UA_TypedArray* p) {
 	p->size = -1;
-	p->vt = &UA_[UA_INVALIDTYPE];
+	p->vt = &UA_.types[UA_INVALIDTYPE];
 	p->elements = UA_NULL;
 	return UA_SUCCESS;
 }
@@ -23,7 +17,7 @@ UA_Int32 UA_TypedArray_new(UA_TypedArray** p) {
 UA_Int32 UA_TypedArray_setType(UA_TypedArray* p, UA_Int32 type) {
 	UA_Int32 retval = UA_ERR_INVALID_VALUE;
 	if (type >= UA_BOOLEAN && type <= UA_INVALIDTYPE) {
-		p->vt = &UA_[type];
+		p->vt = &UA_.types[type];
 		retval = UA_SUCCESS;
 	}
 	return retval;
@@ -156,7 +150,6 @@ void XML_Stack_print(XML_Stack* s) {
 	printf("%s", XML_Stack_path(s));
 }
 
-
 // FIXME: we might want to calculate textAttribIdx from a string and the information given on the stack
 void XML_Stack_handleTextAsElementOf(XML_Stack* p, cstring textAttrib, unsigned int textAttribIdx) {
 	p->parent[p->depth].textAttrib = textAttrib;
@@ -181,7 +174,7 @@ UA_Int32 UA_UInt16_copycstring(cstring src, UA_UInt16* dst) {
 	*dst = atoi(src);
 	return UA_SUCCESS;
 }
-UA_Int32 UA_Int16_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int16* dst, _Bool isStart) {
+UA_Int32 UA_Int16_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_Int16* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -193,7 +186,7 @@ UA_Int32 UA_Int16_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int16* dst, _Bool i
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_Int32_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int32* dst, _Bool isStart) {
+UA_Int32 UA_Int32_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_Int32* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -205,7 +198,7 @@ UA_Int32 UA_Int32_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int32* dst, _Bool i
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_Text_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Byte** dst, _Bool isStart) {
+UA_Int32 UA_Text_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_Byte** dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -222,14 +215,14 @@ UA_Int32 UA_Text_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Byte** dst, _Bool is
 				tmp[strlen(attr[i+1])] = 0;
 				*dst = (UA_Byte*) tmp;
 			} else {
-				printf("UA_Text_decodeXML - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
+				printf("UA_Text_decodeXml - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
 			}
 		}
 	}
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_String_decodeXML(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool isStart) {
+UA_Int32 UA_String_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -238,8 +231,8 @@ UA_Int32 UA_String_decodeXML(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Data", strlen("Data"), (XML_decoder) UA_Text_decodeXML, UA_BYTE, &(dst->data));
-		XML_Stack_addChildHandler(s, "Length", strlen("Length"), (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->length));
+		XML_Stack_addChildHandler(s, "Data", strlen("Data"), (XML_decoder) UA_Text_decodeXmlFromStack, UA_BYTE, &(dst->data));
+		XML_Stack_addChildHandler(s, "Length", strlen("Length"), (XML_decoder) UA_Int32_decodeXmlFromStack, UA_INT32, &(dst->length));
 		XML_Stack_handleTextAsElementOf(s, "Data", 0);
 
 		// set attributes
@@ -247,7 +240,7 @@ UA_Int32 UA_String_decodeXML(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool
 			if (0 == strncmp("Data", attr[i], strlen("Data"))) {
 				UA_String_copycstring(attr[i + 1], dst);
 			} else {
-				printf("UA_String_decodeXML - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
+				printf("UA_String_decodeXml - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
 			}
 		}
 	} else {
@@ -262,7 +255,7 @@ UA_Int32 UA_String_decodeXML(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_NodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool isStart) {
+UA_Int32 UA_NodeId_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_NodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -271,9 +264,9 @@ UA_Int32 UA_NodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"), (XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->namespace));
-		XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"), (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->identifier.numeric));
-		XML_Stack_addChildHandler(s, "Identifier", strlen("Identifier"), (XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
+		XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"), (XML_decoder) UA_Int16_decodeXmlFromStack, UA_INT16, &(dst->namespace));
+		XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"), (XML_decoder) UA_Int32_decodeXmlFromStack, UA_INT32, &(dst->identifier.numeric));
+		XML_Stack_addChildHandler(s, "Identifier", strlen("Identifier"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, UA_NULL);
 		XML_Stack_handleTextAsElementOf(s, "Data", 2);
 
 		// set attributes
@@ -284,7 +277,7 @@ UA_Int32 UA_NodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool
 				dst->identifier.numeric = atoi(attr[i + 1]);
 				dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
 			} else {
-				printf("UA_NodeId_decodeXML - Unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
+				printf("UA_NodeId_decodeXml - Unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
 			}
 		}
 	} else {
@@ -294,7 +287,7 @@ UA_Int32 UA_NodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool
 	}
 	return UA_SUCCESS;
 }
-UA_Int32 UA_ExpandedNodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExpandedNodeId* dst, _Bool isStart) {
+UA_Int32 UA_ExpandedNodeId_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_ExpandedNodeId* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_ExpandedNodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -303,11 +296,11 @@ UA_Int32 UA_ExpandedNodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExpandedNo
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "NodeId", strlen("NodeId"), (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->nodeId));
-		XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"),(XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->nodeId.namespace));
-		XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"),(XML_decoder) UA_Int32_decodeXML, UA_INT32,
+		XML_Stack_addChildHandler(s, "NodeId", strlen("NodeId"), (XML_decoder) UA_NodeId_decodeXmlFromStack, UA_NODEID, &(dst->nodeId));
+		XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"),(XML_decoder) UA_Int16_decodeXmlFromStack, UA_INT16, &(dst->nodeId.namespace));
+		XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"),(XML_decoder) UA_Int32_decodeXmlFromStack, UA_INT32,
 				&(dst->nodeId.identifier.numeric));
-		XML_Stack_addChildHandler(s, "Id", strlen("Id"),(XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
+		XML_Stack_addChildHandler(s, "Id", strlen("Id"),(XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, UA_NULL);
 		XML_Stack_handleTextAsElementOf(s, "Data", 3);
 
 		// set attributes
@@ -319,14 +312,14 @@ UA_Int32 UA_ExpandedNodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExpandedNo
 			} else if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
 				UA_NodeId_copycstring((cstring) attr[i + 1], &(dst->nodeId), s->aliases);
 			} else {
-				printf("UA_ExpandedNodeId_decodeXML - unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
+				printf("UA_ExpandedNodeId_decodeXml - unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
 			}
 		}
 	}
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_LocalizedText_decodeXML(XML_Stack* s, XML_Attr* attr, UA_LocalizedText* dst, _Bool isStart) {
+UA_Int32 UA_LocalizedText_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_LocalizedText* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_LocalizedText entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -335,8 +328,8 @@ UA_Int32 UA_LocalizedText_decodeXML(XML_Stack* s, XML_Attr* attr, UA_LocalizedTe
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		// s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Text", strlen("Text"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->text));
-		XML_Stack_addChildHandler(s, "Locale", strlen("Locale"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->locale));
+		XML_Stack_addChildHandler(s, "Text", strlen("Text"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, &(dst->text));
+		XML_Stack_addChildHandler(s, "Locale", strlen("Locale"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, &(dst->locale));
 		XML_Stack_handleTextAsElementOf(s, "Data", 0);
 
 		// set attributes
@@ -366,7 +359,7 @@ UA_Int32 UA_LocalizedText_decodeXML(XML_Stack* s, XML_Attr* attr, UA_LocalizedTe
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_QualifiedName_decodeXML(XML_Stack* s, XML_Attr* attr, UA_QualifiedName* dst, _Bool isStart) {
+UA_Int32 UA_QualifiedName_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_QualifiedName* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_QualifiedName entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
@@ -375,8 +368,8 @@ UA_Int32 UA_QualifiedName_decodeXML(XML_Stack* s, XML_Attr* attr, UA_QualifiedNa
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Name", strlen("Name"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->name));
-		XML_Stack_addChildHandler(s, "NamespaceIndex", strlen("NamespaceIndex"), (XML_decoder) UA_Int16_decodeXML, UA_STRING,
+		XML_Stack_addChildHandler(s, "Name", strlen("Name"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, &(dst->name));
+		XML_Stack_addChildHandler(s, "NamespaceIndex", strlen("NamespaceIndex"), (XML_decoder) UA_Int16_decodeXmlFromStack, UA_STRING,
 				&(dst->namespaceIndex));
 		XML_Stack_handleTextAsElementOf(s, "Data", 0);
 
@@ -394,8 +387,8 @@ UA_Int32 UA_QualifiedName_decodeXML(XML_Stack* s, XML_Attr* attr, UA_QualifiedNa
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_ReferenceNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ReferenceNode* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_ReferenceNode_decodeXML entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+UA_Int32 UA_ReferenceNode_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_ReferenceNode* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_ReferenceNode_decodeXml entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		// create if necessary
 		if (dst == UA_NULL) {
@@ -404,10 +397,10 @@ UA_Int32 UA_ReferenceNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ReferenceNo
 		}
 		// set handlers
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "ReferenceType", strlen("ReferenceType"),(XML_decoder) UA_NodeId_decodeXML, UA_STRING,
+		XML_Stack_addChildHandler(s, "ReferenceType", strlen("ReferenceType"),(XML_decoder) UA_NodeId_decodeXmlFromStack, UA_STRING,
 				&(dst->referenceTypeId));
-		XML_Stack_addChildHandler(s, "IsForward", strlen("IsForward"), (XML_decoder) UA_Boolean_decodeXML, UA_STRING, &(dst->isInverse));
-		XML_Stack_addChildHandler(s, "Target", strlen("Target"), (XML_decoder) UA_ExpandedNodeId_decodeXML, UA_STRING, &(dst->targetId));
+		XML_Stack_addChildHandler(s, "IsForward", strlen("IsForward"), (XML_decoder) UA_Boolean_decodeXmlFromStack, UA_STRING, &(dst->isInverse));
+		XML_Stack_addChildHandler(s, "Target", strlen("Target"), (XML_decoder) UA_ExpandedNodeId_decodeXmlFromStack, UA_STRING, &(dst->targetId));
 		XML_Stack_handleTextAsElementOf(s, "NodeId", 2);
 
 		// set attributes
@@ -429,53 +422,55 @@ UA_Int32 UA_ReferenceNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ReferenceNo
 }
 
 
-UA_Int32 UA_TypedArray_decodeXML(XML_Stack* s, XML_Attr* attr, UA_TypedArray* dst, _Bool isStart) {
-	UA_Int32 type = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].type;
-	cstring names  = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].name;
-	DBG_VERBOSE(printf("UA_TypedArray_decodeXML - entered with dst=%p,isStart=%d,type={%d,%s},name=%s\n", (void* ) dst, isStart,type,UA_[type].name, names));
-	if (isStart) {
-		if (dst == UA_NULL) {
-			UA_TypedArray_new(&dst);
-			UA_TypedArray_setType(dst, type);
-			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = dst;
-		}
-		// need to map from ArrayName to member name
-		// References - Reference
-		// Aliases - Alias
-		// ListOfXX - XX
-		UA_Int32 length = 0;
-		if (0 == strncmp("ListOf",names,strlen("ListOf"))) {
-			names = &names[strlen("ListOf")];
-			length = strlen(names);
-		} else if ( 0 == strncmp("References",names,strlen("References"))){
-			length = strlen(names) - 1;
-		} else if ( 0 == strncmp("Aliases",names,strlen("Aliases"))){
-			length = strlen(names) - 2;
-		}
-		DBG(printf("UA_TypedArray_decodeXML - add handler for {%.*s}\n", length, names));
-		XML_Stack_addChildHandler(s, names, length, (XML_decoder) UA_[type].decodeXML, type, UA_NULL);
-	} else {
-		// sub element is ready, add to array
-		if (dst->size < 0 || dst->size == 0) {
-			dst->size = 1;
-			UA_alloc((void** )&(dst->elements), dst->size * sizeof(void*));
-			DBG(printf("UA_TypedArray_decodeXML - allocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->elements),dst->size));
-		} else {
-			dst->size++;
-			dst->elements = realloc(dst->elements, dst->size * sizeof(void*));
-			DBG(printf("UA_TypedArray_decodeXML - reallocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst,(void* )(dst->elements), dst->size));
-		}
-		// index starts with 0, therefore size-1
-		DBG_VERBOSE(printf("UA_TypedArray_decodeXML - assign element[%d], src=%p\n", dst->size - 1, (void* )attr));
-		dst->elements[dst->size - 1] = (void*) attr;
-		DBG_VERBOSE(printf("UA_TypedArray_decodeXML - clear %p\n",(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
-		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
-	}
+UA_Int32 UA_TypedArray_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_TypedArray* dst, _Bool isStart) {
+	// Can't fix this code as I don't understand it.
+	/* UA_Int32 type = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].type; */
+	/* cstring names  = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].name; */
+	/* DBG_VERBOSE(printf("UA_TypedArray_decodeXml - entered with dst=%p,isStart=%d,type={%d,%s},name=%s\n", (void* ) dst, isStart,type,UA_types.[type].name, names)); */
+	/* if (isStart) { */
+	/* 	if (dst == UA_NULL) { */
+	/* 		UA_TypedArray_new(&dst); */
+	/* 		UA_TypedArray_setType(dst, type); */
+	/* 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = dst; */
+	/* 	} */
+	/* 	// need to map from ArrayName to member name */
+	/* 	// References - Reference */
+	/* 	// Aliases - Alias */
+	/* 	// ListOfXX - XX */
+	/* 	UA_Int32 length = 0; */
+	/* 	if (0 == strncmp("ListOf",names,strlen("ListOf"))) { */
+	/* 		names = &names[strlen("ListOf")]; */
+	/* 		length = strlen(names); */
+	/* 	} else if ( 0 == strncmp("References",names,strlen("References"))){ */
+	/* 		length = strlen(names) - 1; */
+	/* 	} else if ( 0 == strncmp("Aliases",names,strlen("Aliases"))){ */
+	/* 		length = strlen(names) - 2; */
+	/* 	} */
+	/* 	DBG(printf("UA_TypedArray_decodeXml - add handler for {%.*s}\n", length, names)); */
+	/* 	// Todo. I cannot write to stack from UA_ */
+	/* 	//XML_Stack_addChildHandler(s, names, length, (XML_decoder) UA_.types[type].decodeXml, type, UA_NULL); */
+	/* } else { */
+	/* 	// sub element is ready, add to array */
+	/* 	if (dst->size < 0 || dst->size == 0) { */
+	/* 		dst->size = 1; */
+	/* 		UA_alloc((void** )&(dst->elements), dst->size * sizeof(void*)); */
+	/* 		DBG(printf("UA_TypedArray_decodeXml - allocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->elements),dst->size)); */
+	/* 	} else { */
+	/* 		dst->size++; */
+	/* 		dst->elements = realloc(dst->elements, dst->size * sizeof(void*)); */
+	/* 		DBG(printf("UA_TypedArray_decodeXml - reallocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst,(void* )(dst->elements), dst->size)); */
+	/* 	} */
+	/* 	// index starts with 0, therefore size-1 */
+	/* 	DBG_VERBOSE(printf("UA_TypedArray_decodeXml - assign element[%d], src=%p\n", dst->size - 1, (void* )attr)); */
+	/* 	dst->elements[dst->size - 1] = (void*) attr; */
+	/* 	DBG_VERBOSE(printf("UA_TypedArray_decodeXml - clear %p\n",(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj))); */
+	/* 	s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL; */
+	/* } */
 	return UA_SUCCESS;
 }
 
 
-UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode* dst, _Bool isStart) {
+UA_Int32 UA_DataTypeNode_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_DataTypeNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
@@ -487,11 +482,11 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode
 		}
 
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
-		XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
-		XML_Stack_addChildHandler(s, "BrowseName", strlen("BrowseName"),(XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME, &(dst->description));
-		XML_Stack_addChildHandler(s, "IsAbstract", strlen("IsAbstract"),(XML_decoder) UA_Boolean_decodeXML, UA_BOOLEAN, &(dst->description));
-		XML_Stack_addChildHandler(s, "References", strlen("References"),(XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT, &(dst->displayName));
+		XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT, &(dst->description));
+		XML_Stack_addChildHandler(s, "BrowseName", strlen("BrowseName"),(XML_decoder) UA_QualifiedName_decodeXmlFromStack, UA_QUALIFIEDNAME, &(dst->description));
+		XML_Stack_addChildHandler(s, "IsAbstract", strlen("IsAbstract"),(XML_decoder) UA_Boolean_decodeXmlFromStack, UA_BOOLEAN, &(dst->description));
+		XML_Stack_addChildHandler(s, "References", strlen("References"),(XML_decoder) UA_TypedArray_decodeXmlFromStack, UA_REFERENCENODE, UA_NULL);
 
 		// set missing default attributes
 		dst->nodeClass = UA_NODECLASS_DATATYPE;
@@ -523,7 +518,7 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode
 				UA_TypedArray* array = (UA_TypedArray *) attr;
 				DBG_VERBOSE(printf("finished aliases: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
 				dst->referencesSize = array->size;
-				dst->references = (UA_ReferenceNode**) array->elements;
+				dst->references = (UA_ReferenceNode*) array->elements;
 			}
 		break;
 		}
@@ -531,7 +526,7 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_ObjectNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* dst, _Bool isStart) {
+UA_Int32 UA_ObjectNode_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_ObjectNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
@@ -543,12 +538,12 @@ UA_Int32 UA_ObjectNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* ds
 		}
 
 		// s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
-		XML_Stack_addChildHandler(s, "Description", strlen("Description"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
+		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT, &(dst->displayName));
+		XML_Stack_addChildHandler(s, "Description", strlen("Description"), (XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT, &(dst->description));
 		// FIXME: no idea how to handle SymbolicName automatically. Seems to me that it is the "real" BrowseName
-		//		XML_Stack_addChildHandler(s, "BrowseName", (XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME,&(dst->browseName));
-		XML_Stack_addChildHandler(s, "SymbolicName", strlen("SymbolicName"), (XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME,&(dst->browseName));
-		XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE, UA_NULL);
+		//		XML_Stack_addChildHandler(s, "BrowseName", (XML_decoder) UA_QualifiedName_decodeXml, UA_QUALIFIEDNAME,&(dst->browseName));
+		XML_Stack_addChildHandler(s, "SymbolicName", strlen("SymbolicName"), (XML_decoder) UA_QualifiedName_decodeXmlFromStack, UA_QUALIFIEDNAME,&(dst->browseName));
+		XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXmlFromStack, UA_REFERENCENODE, UA_NULL);
 
 		// set missing default attributes
 		dst->nodeClass = UA_NODECLASS_DATATYPE;
@@ -573,9 +568,9 @@ UA_Int32 UA_ObjectNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* ds
 	} else {
 		if (s->parent[s->depth - 1].activeChild == 3 && attr != UA_NULL ) { // References Array
 			UA_TypedArray* array = (UA_TypedArray*) attr;
-			DBG(printf("UA_ObjectNode_decodeXML finished references: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
+			DBG(printf("UA_ObjectNode_decodeXml finished references: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
 			dst->referencesSize = array->size;
-			dst->references = (UA_ReferenceNode**) array->elements;
+			dst->references = (UA_ReferenceNode*) array->elements;
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
 	}
@@ -583,7 +578,7 @@ UA_Int32 UA_ObjectNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* ds
 }
 
 
-UA_Int32 UA_Variant_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bool isStart) {
+UA_Int32 UA_Variant_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_Variant entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
@@ -595,8 +590,8 @@ UA_Int32 UA_Variant_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bo
 		}
 
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "ListOfExtensionObject", strlen("ListOfExtensionObject"), (XML_decoder) UA_TypedArray_decodeXML, UA_EXTENSIONOBJECT, UA_NULL);
-		XML_Stack_addChildHandler(s, "ListOfLocalizedText", strlen("ListOfLocalizedText"), (XML_decoder) UA_TypedArray_decodeXML, UA_LOCALIZEDTEXT, UA_NULL);
+		XML_Stack_addChildHandler(s, "ListOfExtensionObject", strlen("ListOfExtensionObject"), (XML_decoder) UA_TypedArray_decodeXmlFromStack, UA_EXTENSIONOBJECT, UA_NULL);
+		XML_Stack_addChildHandler(s, "ListOfLocalizedText", strlen("ListOfLocalizedText"), (XML_decoder) UA_TypedArray_decodeXmlFromStack, UA_LOCALIZEDTEXT, UA_NULL);
 
 		// set attributes
 		for (i = 0; attr[i]; i += 2) {
@@ -608,18 +603,18 @@ UA_Int32 UA_Variant_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bo
 	} else {
 		if (s->parent[s->depth - 1].activeChild == 0 && attr != UA_NULL ) { // ExtensionObject
 			UA_TypedArray* array = (UA_TypedArray*) attr;
-			DBG_VERBOSE(printf("UA_Variant_decodeXML - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
+			DBG_VERBOSE(printf("UA_Variant_decodeXml - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
 			dst->arrayLength = array->size;
 			dst->data = array->elements;
-			dst->vt = &UA_[UA_EXTENSIONOBJECT];
+			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;
-			DBG_VERBOSE(printf("UA_Variant_decodeXML - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
+			DBG_VERBOSE(printf("UA_Variant_decodeXml - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
 			dst->arrayLength = array->size;
 			dst->data = array->elements;
-			dst->vt = &UA_[UA_LOCALIZEDTEXT];
+			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;
 		}
@@ -627,7 +622,7 @@ UA_Int32 UA_Variant_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bo
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_ExtensionObject_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExtensionObject* dst, _Bool isStart) {
+UA_Int32 UA_ExtensionObject_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_ExtensionObject* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_ExtensionObject entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
@@ -639,8 +634,8 @@ UA_Int32 UA_ExtensionObject_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Extension
 		}
 
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "TypeId", strlen("TypeId"), (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->typeId));
-		// XML_Stack_addChildHandler(s, "Body", strlen("Body"), (XML_decoder) UA_Body_decodeXML, UA_LOCALIZEDTEXT, UA_NULL);
+		XML_Stack_addChildHandler(s, "TypeId", strlen("TypeId"), (XML_decoder) UA_NodeId_decodeXmlFromStack, UA_NODEID, &(dst->typeId));
+		// XML_Stack_addChildHandler(s, "Body", strlen("Body"), (XML_decoder) UA_Body_decodeXml, UA_LOCALIZEDTEXT, UA_NULL);
 
 		// set attributes
 		for (i = 0; attr[i]; i += 2) {
@@ -660,7 +655,7 @@ _Bool UA_NodeId_isBuiltinType(UA_NodeId* nodeid) {
 			);
 }
 
-UA_Int32 UA_VariableNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_VariableNode* dst, _Bool isStart) {
+UA_Int32 UA_VariableNode_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_VariableNode* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_VariableNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
@@ -672,14 +667,14 @@ UA_Int32 UA_VariableNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_VariableNode
 		}
 
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+		XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT,
 				&(dst->displayName));
-		XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+		XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXmlFromStack, UA_LOCALIZEDTEXT,
 				&(dst->description));
-		XML_Stack_addChildHandler(s, "DataType", strlen("DataType"),(XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->dataType));
-		XML_Stack_addChildHandler(s, "ValueRank", strlen("ValueRank"),(XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->valueRank));
-		XML_Stack_addChildHandler(s, "Value", strlen("Value"),(XML_decoder) UA_Variant_decodeXML, UA_VARIANT, &(dst->value));
-		XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE,
+		XML_Stack_addChildHandler(s, "DataType", strlen("DataType"),(XML_decoder) UA_NodeId_decodeXmlFromStack, UA_NODEID, &(dst->dataType));
+		XML_Stack_addChildHandler(s, "ValueRank", strlen("ValueRank"),(XML_decoder) UA_Int32_decodeXmlFromStack, UA_INT32, &(dst->valueRank));
+		XML_Stack_addChildHandler(s, "Value", strlen("Value"),(XML_decoder) UA_Variant_decodeXmlFromStack, UA_VARIANT, &(dst->value));
+		XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXmlFromStack, UA_REFERENCENODE,
 		UA_NULL);
 
 		// set missing default attributes
@@ -693,10 +688,10 @@ UA_Int32 UA_VariableNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_VariableNode
 				UA_NodeId_copycstring(attr[i + 1], &(dst->dataType), s->aliases);
 				if (UA_NodeId_isBuiltinType(&(dst->dataType))) {
 					dst->value.encodingMask = dst->dataType.identifier.numeric;
-					dst->value.vt = &UA_[UA_ns0ToVTableIndex(dst->dataType.identifier.numeric)];
+					dst->value.vt = &UA_.types[UA_ns0ToVTableIndex(&dst->dataType)];
 				} else {
 					dst->value.encodingMask = UA_EXTENSIONOBJECT_NS0;
-					dst->value.vt = &UA_[UA_EXTENSIONOBJECT];
+					dst->value.vt = &UA_.types[UA_EXTENSIONOBJECT];
 				}
 			} else if (0 == strncmp("ValueRank", attr[i], strlen("ValueRank"))) {
 				dst->valueRank = atoi(attr[i + 1]);
@@ -719,9 +714,9 @@ UA_Int32 UA_VariableNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_VariableNode
 	} else {
 		if (s->parent[s->depth - 1].activeChild == 5 && attr != UA_NULL) { // References
 			UA_TypedArray* array = (UA_TypedArray*) attr;
-			DBG(printf("UA_VariableNode_decodeXML - finished references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
+			DBG(printf("UA_VariableNode_decodeXml - finished references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
 			dst->referencesSize = array->size;
-			dst->references = (UA_ReferenceNode**) array->elements;
+			dst->references = (UA_ReferenceNode*) array->elements;
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
 	}
@@ -742,7 +737,7 @@ void print_node(UA_Node const * node) {
 		UA_Int32 i;
 		for (i=0;i<node->referencesSize;i++) {
 			printf("\t\t.element[%d]", i);
-			UA_ReferenceNode_println("=",node->references[i]);
+			UA_ReferenceNode_println("=",&node->references[i]);
 		}
 		switch (node->nodeClass) {
 		case UA_NODECLASS_VARIABLE: {
@@ -759,19 +754,21 @@ void print_node(UA_Node const * node) {
 			printf("\t.value.type.name=%s\n", p->value.vt->name);
 			printf("\t.value.array.length=%d\n", p->value.arrayLength);
 			UA_Int32 i;
+			UA_Byte *data = (UA_Byte*) p->value.data;
 			for (i=0;i<p->value.arrayLength || (p->value.arrayLength==-1 && i==0);++i) {
-				printf("\t.value.array.element[%d]=%p", i, (p->value.data == UA_NULL ? UA_NULL : p->value.data[i]));
-				switch (p->value.vt->ns0Id) {
+				UA_Byte *currentData = data + (i*p->value.vt->memSize);
+				printf("\t.value.array.element[%d]=%p", i, currentData);
+				switch (p->value.vt->typeId.identifier.numeric) {
 				case UA_LOCALIZEDTEXT_NS0: {
 					if (p->value.data != UA_NULL) {
-						UA_LocalizedText* ltp = (UA_LocalizedText*) p->value.data[i];
+						UA_LocalizedText* ltp = (UA_LocalizedText*) currentData;
 						printf(",enc=%d,locale={%d,{%.*s}},text={%d,{%.*s}}",ltp->encodingMask,ltp->locale.length,ltp->locale.length,ltp->locale.data,ltp->text.length,ltp->text.length,ltp->text.data);
 					}
 				}
 				break;
 				case UA_EXTENSIONOBJECT_NS0: {
 					if (p->value.data != UA_NULL) {
-						UA_ExtensionObject* eo = (UA_ExtensionObject*) p->value.data[i];
+						UA_ExtensionObject* eo = (UA_ExtensionObject*) currentData;
 						if (eo == UA_NULL) {
 							printf(",(null)");
 						} else {
@@ -794,7 +791,7 @@ void print_node(UA_Node const * node) {
 	}
 }
 
-UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias* dst, _Bool isStart) {
+UA_Int32 UA_NodeSetAlias_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_NodeSetAlias entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		// create if necessary
@@ -804,8 +801,8 @@ UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias
 		}
 		// set handlers
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->alias));
-		XML_Stack_addChildHandler(s, "Value", strlen("Value"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->value));
+		XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, &(dst->alias));
+		XML_Stack_addChildHandler(s, "Value", strlen("Value"), (XML_decoder) UA_String_decodeXmlFromStack, UA_STRING, &(dst->value));
 		XML_Stack_handleTextAsElementOf(s, "Data", 1);
 
 		// set attributes
@@ -828,7 +825,7 @@ UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAliases* dst, _Bool isStart) {
+UA_Int32 UA_NodeSetAliases_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_NodeSetAliases* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_NodeSetALiases entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -836,7 +833,7 @@ UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAli
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_NodeSetAlias_decodeXML, UA_INVALIDTYPE, UA_NULL);
+		XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_NodeSetAlias_decodeXmlFromStack, UA_INVALIDTYPE, UA_NULL);
 	} else {
 		// sub element is ready, add to array
 		if (dst->size < 0 || dst->size == 0) {
@@ -861,7 +858,7 @@ UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAli
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_NodeSet_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart) {
+UA_Int32 UA_NodeSet_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart) {
 	DBG_VERBOSE(printf("UA_NodeSet entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -869,24 +866,24 @@ UA_Int32 UA_NodeSet_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bo
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Aliases", strlen("Aliases"), (XML_decoder) UA_NodeSetAliases_decodeXML, UA_INVALIDTYPE,
+		XML_Stack_addChildHandler(s, "Aliases", strlen("Aliases"), (XML_decoder) UA_NodeSetAliases_decodeXmlFromStack, UA_INVALIDTYPE,
 				&(dst->aliases));
-		XML_Stack_addChildHandler(s, "UADataType", strlen("UADataType"), (XML_decoder) UA_DataTypeNode_decodeXML, UA_DATATYPENODE, UA_NULL);
-		XML_Stack_addChildHandler(s, "UAVariableType", strlen("UAVariableType"), (XML_decoder) UA_VariableTypeNode_decodeXML, UA_VARIABLETYPENODE, UA_NULL);
-		XML_Stack_addChildHandler(s, "UAVariable", strlen("UAVariable"), (XML_decoder) UA_VariableNode_decodeXML, UA_VARIABLENODE, UA_NULL);
-		XML_Stack_addChildHandler(s, "UAObjectType", strlen("UAObjectType"), (XML_decoder) UA_ObjectTypeNode_decodeXML, UA_OBJECTTYPENODE, UA_NULL);
-		XML_Stack_addChildHandler(s, "UAObject", strlen("UAObject"), (XML_decoder) UA_ObjectNode_decodeXML, UA_OBJECTNODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UADataType", strlen("UADataType"), (XML_decoder) UA_DataTypeNode_decodeXmlFromStack, UA_DATATYPENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UAVariableType", strlen("UAVariableType"), (XML_decoder) UA_VariableTypeNode_decodeXmlFromStack, UA_VARIABLETYPENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UAVariable", strlen("UAVariable"), (XML_decoder) UA_VariableNode_decodeXmlFromStack, UA_VARIABLENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UAObjectType", strlen("UAObjectType"), (XML_decoder) UA_ObjectTypeNode_decodeXmlFromStack, UA_OBJECTTYPENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UAObject", strlen("UAObject"), (XML_decoder) UA_ObjectNode_decodeXmlFromStack, UA_OBJECTNODE, UA_NULL);
 	} else {
 		if (s->parent[s->depth - 1].activeChild == 0 && attr != UA_NULL) {
 			UA_NodeSetAliases* aliases = (UA_NodeSetAliases*) attr;
-			DBG(printf("UA_NodeSet_decodeXML - finished aliases: aliases=%p, size=%d\n",(void*)aliases,(aliases==UA_NULL)?-1:aliases->size));
+			DBG(printf("UA_NodeSet_decodeXml - finished aliases: aliases=%p, size=%d\n",(void*)aliases,(aliases==UA_NULL)?-1:aliases->size));
 			s->aliases = aliases;
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		} else if (attr != UA_NULL && (s->parent[s->depth - 1].activeChild == 3 ||  s->parent[s->depth - 1].activeChild == 5)) {
 			UA_Node* node = (UA_Node*) attr;
-			DBG(printf("UA_NodeSet_decodeXML - finished node: node=%p\n", (void* )node));
+			DBG(printf("UA_NodeSet_decodeXml - finished node: node=%p\n", (void* )node));
 			Namespace_insert(dst->ns, node);
-			DBG(printf("UA_NodeSet_decodeXML - Inserting "));
+			DBG(printf("UA_NodeSet_decodeXml - Inserting "));
 			DBG(print_node(node));
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
@@ -1009,7 +1006,7 @@ UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char*
 
 	UA_NodeSet n;
 	UA_NodeSet_init(&n, 0);
-	XML_Stack_addChildHandler(&s, "UANodeSet", strlen("UANodeSet"), (XML_decoder) UA_NodeSet_decodeXML, UA_INVALIDTYPE, &n);
+	XML_Stack_addChildHandler(&s, "UANodeSet", strlen("UANodeSet"), (XML_decoder) UA_NodeSet_decodeXmlFromStack, UA_INVALIDTYPE, &n);
 
 	XML_Parser parser = XML_ParserCreate(NULL);
 	XML_SetUserData(parser, &s);

+ 50 - 46
src/ua_xml.h

@@ -1,10 +1,3 @@
-/*
- * ua_xml.h
- *
- *  Created on: 03.05.2014
- *      Author: mrt
- */
-
 #ifndef __UA_XML_H__
 #define __UA_XML_H__
 
@@ -15,20 +8,65 @@
 #include <ctype.h> // isspace
 #include <unistd.h> // read
 
-#include "opcua.h"
-#include "ua_namespace.h"
+#include "ua_types.h"
+
+struct XML_Stack;
+typedef char const * const XML_Attr;
+typedef char const * cstring;
+#define XML_STACK_MAX_DEPTH 10
+#define XML_STACK_MAX_CHILDREN 40
+typedef UA_Int32 (*XML_decoder)(struct XML_Stack* s, XML_Attr* attr, void* dst, UA_Boolean isStart);
+
+/** @brief A readable shortcut for NodeIds. A list of aliases is intensively used in the namespace0-xml-files */
+typedef struct UA_NodeSetAlias {
+	UA_String alias;
+	UA_String value;
+} UA_NodeSetAlias;
+UA_TYPE_PROTOTYPES(UA_NodeSetAlias)
+
+/** @brief UA_NodeSetAliases - a list of aliases */
+typedef struct UA_NodeSetAliases {
+	UA_Int32 size;
+	UA_NodeSetAlias **aliases;
+} UA_NodeSetAliases;
+UA_TYPE_PROTOTYPES(UA_NodeSetAliases)
+
+typedef struct XML_child {
+ cstring     name;
+ UA_Int32    length;
+ UA_Int32    type;
+ XML_decoder elementHandler;
+ void       *obj;
+} XML_child;
+
+typedef struct XML_Parent {
+ cstring   name;
+ int       textAttribIdx;     // -1 - not set
+ cstring   textAttrib;
+ int       activeChild;       // -1 - no active child
+ int       len;               // -1 - empty set
+ XML_child children[XML_STACK_MAX_CHILDREN];
+} XML_Parent;
+
+typedef struct XML_Stack {
+ int                depth;
+ XML_Parent         parent[XML_STACK_MAX_DEPTH];
+ UA_NodeSetAliases *aliases;     // shall point to the aliases of the NodeSet after reading
+} XML_Stack;
+
+void XML_Stack_init(XML_Stack* p, cstring name);
+void XML_Stack_print(XML_Stack* s);
 
 UA_Int32 UA_Boolean_copycstring(cstring src, UA_Boolean* dst);
 UA_Int32 UA_Int16_copycstring(cstring src, UA_Int16* dst);
 UA_Int32 UA_UInt16_copycstring(cstring src, UA_UInt16* dst) ;
 UA_Boolean UA_NodeId_isBuiltinType(UA_NodeId* nodeid);
-void print_node(UA_Node const * node);
 
 /** @brief an object to hold a typed array */
 typedef struct UA_TypedArray {
 	UA_Int32 size;
-	UA_VTable* vt;
-	void** elements;
+	UA_VTable_Entry* vt;
+	void* elements;
 } UA_TypedArray;
 
 /** @brief init typed array with size=-1 and an UA_INVALIDTYPE */
@@ -39,30 +77,6 @@ UA_Int32 UA_TypedArray_new(UA_TypedArray** p);
 UA_Int32 UA_TypedArray_setType(UA_TypedArray* p, UA_Int32 type);
 UA_Int32 UA_TypedArray_decodeXML(XML_Stack* s, XML_Attr* attr, UA_TypedArray* dst, _Bool isStart);
 
-UA_Int32 UA_NodeSetAlias_init(UA_NodeSetAlias* p);
-UA_Int32 UA_NodeSetAlias_new(UA_NodeSetAlias** p);
-UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias* dst, _Bool isStart);
-
-UA_Int32 UA_NodeSetAliases_init(UA_NodeSetAliases* p);
-UA_Int32 UA_NodeSetAliases_new(UA_NodeSetAliases** p);
-UA_Int32 UA_NodeSetAliases_println(cstring label, UA_NodeSetAliases *p);
-UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAliases* dst, _Bool isStart);
-
-typedef struct UA_NodeSet {
-	Namespace* ns;
-	UA_NodeSetAliases aliases;
-} UA_NodeSet;
-
-/** @brief init typed array with size=-1 and an UA_INVALIDTYPE */
-UA_Int32 UA_NodeSet_init(UA_NodeSet* p, UA_UInt32 nsid);
-UA_Int32 UA_NodeSet_new(UA_NodeSet** p, UA_UInt32 nsid);
-UA_Int32 UA_NodeId_copycstring(cstring src, UA_NodeId* dst, UA_NodeSetAliases* aliases);
-UA_Int32 UA_NodeSet_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart);
-
-UA_Int32 UA_ExpandedNodeId_copycstring(cstring src, UA_ExpandedNodeId* dst, UA_NodeSetAliases* aliases);
-
-void XML_Stack_init(XML_Stack* p, cstring name);
-void XML_Stack_print(XML_Stack* s);
 
 /** @brief add a reference to a handler (@see XML_Stack_addChildHandler) for text data
  *
@@ -104,14 +118,4 @@ UA_Int32 XML_isSpace(cstring s, int len);
 void XML_Stack_handleText(void * data, const char *txt, int len);
 void XML_Stack_endElement(void *data, const char *el);
 
-/** @brief load a namespace from an XML-File
- *
- * @param[in/out] ns the address of the namespace ptr
- * @param[in] namespaceId the numeric id of the namespace
- * @param[in] rootName the name of the root element of the hierarchy (not used?)
- * @param[in] fileName the name of an existing file, e.g. Opc.Ua.NodeSet2.xml
- */
-UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char* rootName,const char* fileName);
-
-
 #endif // __UA_XML_H__

+ 35 - 0
src/ua_xml_namespace.h

@@ -0,0 +1,35 @@
+#include "ua_namespace.h"
+#include "ua_xml.h"
+
+void print_node(UA_Node const * node);
+UA_Int32 UA_NodeSetAlias_init(UA_NodeSetAlias* p);
+UA_Int32 UA_NodeSetAlias_new(UA_NodeSetAlias** p);
+UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias* dst, _Bool isStart);
+
+UA_Int32 UA_NodeSetAliases_init(UA_NodeSetAliases* p);
+UA_Int32 UA_NodeSetAliases_new(UA_NodeSetAliases** p);
+UA_Int32 UA_NodeSetAliases_println(cstring label, UA_NodeSetAliases *p);
+UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAliases* dst, _Bool isStart);
+
+typedef struct UA_NodeSet {
+	Namespace* ns;
+	UA_NodeSetAliases aliases;
+} UA_NodeSet;
+
+/** @brief init typed array with size=-1 and an UA_INVALIDTYPE */
+UA_Int32 UA_NodeSet_init(UA_NodeSet* p, UA_UInt32 nsid);
+UA_Int32 UA_NodeSet_new(UA_NodeSet** p, UA_UInt32 nsid);
+UA_Int32 UA_NodeId_copycstring(cstring src, UA_NodeId* dst, UA_NodeSetAliases* aliases);
+UA_Int32 UA_NodeSet_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart);
+
+UA_Int32 UA_ExpandedNodeId_copycstring(cstring src, UA_ExpandedNodeId* dst, UA_NodeSetAliases* aliases);
+
+/** @brief load a namespace from an XML-File
+ *
+ * @param[in/out] ns the address of the namespace ptr
+ * @param[in] namespaceId the numeric id of the namespace
+ * @param[in] rootName the name of the root element of the hierarchy (not used?)
+ * @param[in] fileName the name of an existing file, e.g. Opc.Ua.NodeSet2.xml
+ */
+UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char* rootName,const char* fileName);
+

+ 1 - 0
src/util/ua_indexedList.c

@@ -1,4 +1,5 @@
 #include "ua_indexedList.h"
+#include "ua_util.h"
 
 void UA_indexedList_defaultFreer(void* payload){
 	UA_list_defaultFreer(payload);

+ 1 - 0
src/util/ua_list.c

@@ -1,4 +1,5 @@
 #include "ua_list.h"
+#include "ua_util.h"
 
 void UA_list_defaultFreer(void* payload){
 	if(payload){

+ 0 - 25
tools/Makefile.am

@@ -1,25 +0,0 @@
-SRC_DIR = $(top_builddir)/src
-INCLUDE_DIR = $(top_builddir)/include
-AUTO_NAME = opcua
-NS0_NAME = ua_namespace_0
-
-all-local: $(AUTO_NAME).cgen $(AUTO_NAME).hgen $(NS0_NAME).cgen $(NS0_NAME).hgen $(bin_PROGRAMS)
-
-$(AUTO_NAME).cgen $(AUTO_NAME).hgen: Opc.Ua.Types.bsd generate_builtin.py
-	python generate_builtin.py Opc.Ua.Types.bsd $(AUTO_NAME)
-	cp $(AUTO_NAME).cgen $(SRC_DIR)/$(AUTO_NAME).c
-	cp $(AUTO_NAME).hgen $(INCLUDE_DIR)/$(AUTO_NAME).h
-	
-$(NS0_NAME).cgen $(NS0_NAME).hgen: NodeIds.csv generate_namespace.py 
-	python generate_namespace.py NodeIds.csv $(NS0_NAME)
-	cp $(NS0_NAME).cgen $(SRC_DIR)/$(NS0_NAME).c
-	cp $(NS0_NAME).hgen $(INCLUDE_DIR)/$(NS0_NAME).h
-
-PHONY: clean-autogenerated
-clean-autogenerated:
-	rm -rf $(AUTO_NAME).cgen $(AUTO_NAME).hgen
-	rm -rf $(SRC_DIR)/$(AUTO_NAME).c $(INCLUDE_DIR)/$(AUTO_NAME).h
-	rm -rf $(NS0_NAME).cgen $(NS0_NAME).hgen
-	rm -rf $(SRC_DIR)/$(NS0_NAME).c $(INCLUDE_DIR)/$(NS0_NAME).h
-
-clean-local: clean-autogenerated

+ 195 - 229
tools/generate_builtin.py

@@ -6,34 +6,41 @@ import getpass
 from collections import OrderedDict
 import re
 from lxml import etree
+import inspect
 
 if len(sys.argv) != 3:
 	print("Usage: python generate_builtin.py <path/to/Opc.Ua.Types.bsd> <outfile w/o extension>", file=sys.stdout)
 	exit(0)
 
-# types that are coded manually 
-exclude_types = set(["Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32",
-					"Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid",
-					"ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "StatusCode", 
-					"QualifiedName", "LocalizedText", "ExtensionObject", "DataValue",
-					 "Variant", "DiagnosticInfo", "IntegerId"])
+ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
+tree = etree.parse(sys.argv[1])
+types = tree.xpath("/opc:TypeDictionary/*[not(self::opc:Import)]", namespaces=ns)
 
-# do not forget to get rid of these excludes once it works
-exclude_xml_decode = set(["UA_ReferenceNode", "UA_ObjectNode", "UA_VariableNode", "UA_DataTypeNode"])
+fh = open(sys.argv[2] + ".h",'w');
+fc = open(sys.argv[2] + ".c",'w');
 
-elementary_size = {"Boolean":1, "SByte":1, "Byte":1, "Int16":2, "UInt16":2, "Int32":4, "UInt32":4,
-                   "Int64":8, "UInt64":8, "Float":4, "Double":8, "DateTime":8, "StatusCode":4}
+# dirty hack. we go up the call frames to access local variables of the calling
+# function. this allows to shorten code and get %()s replaces with less clutter.
+def printh(string):
+    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fh)
 
-# do not forget to get rid of these excludes once it works
-exclude_xml_decode = set(["UA_ReferenceNode", "UA_ObjectNode", "UA_VariableNode", "UA_DataTypeNode"])
+def printc(string):
+    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fc)
 
-enum_types = []
-structured_types = []
-printed_types = exclude_types # types that were already printed and which we can use in the structures to come
+# types that are coded manually 
+existing_types = set(["Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32",
+                     "Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid",
+                     "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "StatusCode", 
+                     "QualifiedName", "LocalizedText", "ExtensionObject", "DataValue",
+                     "Variant", "DiagnosticInfo"])
+
+fixed_size = set(["UA_Boolean", "UA_SByte", "UA_Byte", "UA_Int16", "UA_UInt16",
+                  "UA_Int32", "UA_UInt32", "UA_Int64", "UA_UInt64", "UA_Float",
+                  "UA_Double", "UA_DateTime", "UA_Guid", "UA_StatusCode"])
 
 # types we do not want to autogenerate
 def skipType(name):
-    if name in exclude_types:
+    if name in existing_types:
         return True
     if re.search("NodeId$", name) != None:
         return True
@@ -52,235 +59,188 @@ def printableStructuredType(element):
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
             typename = stripTypename(child.get("TypeName"))
-            if typename not in printed_types:
+            if typename not in existing_types:
                 return False
     return True
 
-# There are three types of types in the bsd file:
-# StructuredType, EnumeratedType OpaqueType
-
 def createEnumerated(element):	
     valuemap = OrderedDict()
     name = "UA_" + element.get("Name")
-    enum_types.append(name)
+    fixed_size.add(name)
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/** @brief " + child.text + " */", end='\n', file=fh)
+            printh("/** @brief " + child.text + " */")
         if child.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedValue":
             valuemap[name + "_" + child.get("Name")] = child.get("Value")
     valuemap = OrderedDict(sorted(valuemap.iteritems(), key=lambda (k,v): int(v)))
-    print("typedef UA_UInt32 " + name + ";", end='\n', file=fh);
-    print("enum " + name + "_enum { \n\t" + ",\n\t".join(map(lambda (key, value) : key.upper() + " = " + value, valuemap.iteritems())) + "\n};", end='\n', file=fh)
-    print("UA_TYPE_METHOD_PROTOTYPES (" + name + ")", end='\n', file=fh)
-    print("UA_TYPE_METHOD_CALCSIZE_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_ENCODEBINARY_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DECODEBINARY_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_INIT_AS("+name+", UA_UInt32)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_UInt32)",'\n', file=fc)  
-    print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DECODEXML_NOTIMPL("+name+")", end='\n', file=fc)
-    return
+    printh("typedef UA_UInt32 " + name + ";")
+    printh("enum " + name + "_enum { \n\t" +
+           ",\n\t".join(map(lambda (key, value) : key.upper() + " = " + value, valuemap.iteritems())) +
+           "\n};")
+    printh("UA_TYPE_PROTOTYPES (" + name + ")")
+    printh("UA_TYPE_BINARY_ENCODING(" + name + ")")
+    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+    printc("UA_TYPE_AS(" + name + ", UA_UInt32)")
+    printc("UA_TYPE_BINARY_ENCODING_AS(" + name + ", UA_UInt32)")
+    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s\n)''')
+
+def createOpaque(element):
+    name = "UA_" + element.get("Name")
+    for child in element:
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
+            printh("/** @brief " + child.text + " */")
+    printh("typedef UA_ByteString %(name)s;")
+    printh("UA_TYPE_PROTOTYPES(%(name)s)")
+    printh("UA_TYPE_BINARY_ENCODING(%(name)s)")
+    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+    printc("UA_TYPE_AS(%(name)s, UA_ByteString)")
+    printc("UA_TYPE_BINARY_ENCODING_AS(%(name)s, UA_ByteString)")
+    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)\n''')
+
     
 def createStructured(element):
-    valuemap = OrderedDict()
     name = "UA_" + element.get("Name")
-    print("\n/** @name " + name + " */\n", file=fh)
 
+    # 1) Are there arrays in the type?
     lengthfields = set()
     for child in element:
-		if child.get("LengthField"):
-			lengthfields.add(child.get("LengthField"))
-	
+        if child.get("LengthField"):
+            lengthfields.add(child.get("LengthField"))
+
+    # 2) Store members in membermap (name->type).
+    membermap = OrderedDict()
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/** @brief " + child.text + " */", end='\n', file=fh)
+            printh("/** @brief " + child.text + " */")
         elif child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
             if child.get("Name") in lengthfields:
                 continue
             childname = camlCase2CCase(child.get("Name"))
             typename = stripTypename(child.get("TypeName"))
             if child.get("LengthField"):
-                valuemap[childname] = typename + "**"
+                membermap[childname] = "UA_" + typename + "*"
             else:
-                valuemap[childname] = typename
-
-    print("typedef struct " + name + " {", end='\n', file=fh)
-    if len(valuemap) == 0:
-		typename = stripTypename(element.get("BaseType"))
-		childname = camlCase2CCase(typename)
-		valuemap[childname] = typename 
-    for n,t in valuemap.iteritems():
-		if t.find("**") != -1:
-			print("\t" + "UA_Int32 " + n + "Size;", end='\n', file=fh)
-		print("\t" + "UA_" + t + " " + n + ";", end='\n', file=fh)
-    print("} " + name + ";", end='\n', file=fh)
-
-    print("UA_Int32 " + name + "_calcSize(" + name + " const* ptr);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_encodeBinary(" + name + " const* src, UA_Int32* pos, UA_ByteString* dst);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_decodeBinary(UA_ByteString const* src, UA_Int32* pos, " + name + "* dst);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_decodeXML(XML_Stack* s, XML_Attr* attr, " + name + "* dst, _Bool isStart);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_delete("+ name + "* p);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_deleteMembers(" + name + "* p);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_init("+ name + " * p);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_new(" + name + " ** p);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_copy(" + name + "* src, " + name + "* dst);", end='\n', file=fh)
-
-    print("UA_Int32 "  + name + "_calcSize(" + name + " const * ptr) {", end='', file=fc)
-    print("\n\tif(ptr==UA_NULL){return sizeof("+ name +");}", end='', file=fc)
-    print("\n\treturn 0", end='', file=fc)
-
-	# code _calcSize
-    for n,t in valuemap.iteritems():
-		if t in elementary_size:
-			print('\n\t + sizeof(UA_' + t + ") // " + n, end='', file=fc)
-		else:
-			if t in enum_types:
-				print('\n\t + 4 //' + n, end='', file=fc) # enums are all 32 bit
-			elif t.find("**") != -1:
-				print("\n\t + 0 //" + n + "Size is included in UA_Array_calcSize", end='', file=fc),
-				print("\n\t + UA_Array_calcSize(ptr->" + n + "Size, UA_" + t[0:t.find("*")].upper() + ", (void const**) ptr->" + n +")", end='', file=fc)
-			elif t.find("*") != -1:
-				print('\n\t + ' + "UA_" + t[0:t.find("*")] + "_calcSize(ptr->" + n + ')', end='', file=fc)
-			else:
-				print('\n\t + ' + "UA_" + t + "_calcSize(&(ptr->" + n + '))', end='', file=fc)
-
-    print("\n\t;\n}\n", end='\n', file=fc)
-
-    print("UA_Int32 "+name+"_encodeBinary("+name+" const * src, UA_Int32* pos, UA_ByteString* dst) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
-	# code _encode
-    for n,t in valuemap.iteritems():
-		if t in elementary_size:
-			print('\tretval |= UA_'+t+'_encodeBinary(&(src->'+n+'),pos,dst);', end='\n', file=fc)
-		else:
-			if t in enum_types:
-				print('\tretval |= UA_'+t+'_encodeBinary(&(src->'+n+'),pos,dst);', end='\n', file=fc)
-			elif t.find("**") != -1:
-				print('\t//retval |= UA_Int32_encodeBinary(&(src->'+n+'Size),pos,dst); // encode size managed by UA_Array_encodeBinary', end='\n', file=fc)
-				print("\tretval |= UA_Array_encodeBinary((void const**) (src->"+n+"),src->"+n+"Size, UA_" + t[0:t.find("*")].upper()+",pos,dst);", end='\n', file=fc)
-			elif t.find("*") != -1:
-				print('\tretval |= UA_' + t[0:t.find("*")] + "_encodeBinary(src->" + n + ',pos,dst);', end='\n', file=fc)
-			else:
-				print('\tretval |= UA_'+t+"_encodeBinary(&(src->"+n+"),pos,dst);", end='\n', file=fc)
-    print("\treturn retval;\n}\n", end='\n', file=fc)
-
-	# code _decodeBinary
-    print("UA_Int32 "+name+"_decodeBinary(UA_ByteString const * src, UA_Int32* pos, " + name + "* dst) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
-    print('\t'+name+'_init(dst);', end='\n', file=fc)
-    for n,t in valuemap.iteritems():
-        if t in elementary_size:
-            print('\tCHECKED_DECODE(UA_'+t+'_decodeBinary(src,pos,&(dst->'+n+')), '+name+'_deleteMembers(dst));', end='\n', file=fc)
+                membermap[childname] = "UA_" + typename
+
+    # 3) Print structure
+    if len(membermap) > 0:
+        printh("typedef struct %(name)s {")
+        for n,t in membermap.iteritems():
+	    if t.find("*") != -1:
+	        printh("\t" + "UA_Int32 " + n + "Size;")
+            printh("\t%(t)s %(n)s;")
+        printh("} %(name)s;")
+    else:
+        printh("typedef void* %(name)s;")
+        
+
+    # 3) function prototypes
+    printh("UA_TYPE_PROTOTYPES(" + name + ")")
+    printh("UA_TYPE_BINARY_ENCODING(" + name + ")")
+    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+
+    # 4) CalcSizeBinary
+    printc('''UA_Int32 %(name)s_calcSizeBinary(%(name)s const * ptr) {
+    \tif(ptr==UA_NULL) return sizeof(%(name)s);
+    \treturn 0''')
+    has_fixed_size = True
+    for n,t in membermap.iteritems():
+        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)")
+            has_fixed_size = False
         else:
-            if t in enum_types:
-                print('\tCHECKED_DECODE(UA_'+t+'_decodeBinary(src,pos,&(dst->'+n+')), '+name+'_deleteMembers(dst));', end='\n', file=fc)
-            elif t.find("**") != -1:
-            	# decode size
-		print('\tCHECKED_DECODE(UA_Int32_decodeBinary(src,pos,&(dst->'+n+'Size)), ' +
-                      name + '_deleteMembers(dst)); // decode size', end='\n', file=fc)
-		# allocate memory for array
-		print("\tCHECKED_DECODE(UA_Array_new((void***)&dst->"+n+", dst->"+n+"Size, UA_"+t[0:t.find("*")].upper()+"), dst->" +
-                      n + " = UA_NULL; "+name+'_deleteMembers(dst));', end='\n', file=fc)
-		print("\tCHECKED_DECODE(UA_Array_decodeBinary(src,dst->"+n+"Size, UA_" + t[0:t.find("*")].upper() +
-                      ",pos,(void *** const) (&dst->"+n+")), "+name+'_deleteMembers(dst));', end='\n', file=fc)
-            elif t.find("*") != -1:
-		#allocate memory using new
-		print('\tCHECKED_DECODE(UA_'+ t[0:t.find("*")] +"_new(&(dst->" + n + ")), "+name+'_deleteMembers(dst));', end='\n', file=fc)
-		print('\tCHECKED_DECODE(UA_' + t[0:t.find("*")] + "_decodeBinary(src,pos,dst->"+ n +"), "+name+'_deleteMembers(dst));', end='\n', file=fc)
-            else:
-                print('\tCHECKED_DECODE(UA_'+t+"_decodeBinary(src,pos,&(dst->"+n+")), "+name+'_deleteMembers(dst));', end='\n', file=fc)
-    print("\treturn retval;\n}\n", end='\n', file=fc)
- 
-    if not name in exclude_xml_decode:
-        print("UA_Int32 "+name+"_decodeXML(XML_Stack* s, XML_Attr* attr, " + name + "* dst, _Bool isStart)", end='\n', file=fc)
-        print('''{
-        DBG_VERBOSE(printf("'''+name+'''_decodeXML entered with dst=%p,isStart=%d\\n", (void* ) dst, isStart));
-        return UA_ERR_NOT_IMPLEMENTED;}''', end='\n', file=fc)
+            printc('\t + %(t)s_calcSizeBinary(&ptr->%(n)s)')
+            has_fixed_size = False
+    printc("\t;\n}\n")
+    if has_fixed_size:
+        fixed_size.add(name)
+
+    # 5) EncodeBinary
+    printc('''UA_Int32 %(name)s_encodeBinary(%(name)s const * src, UA_ByteString* dst, UA_UInt32 *offset) {
+    \tUA_Int32 retval = UA_SUCCESS;''')
+    for n,t in membermap.iteritems():
+        if t.find("*") != -1:
+            printc('\tretval |= UA_Int32_encodeBinary(&src->%(n)sSize,dst, offset);')
+            printc("\tretval |= UA_Array_encodeBinary(&src->%(n)s,src->%(n)sSize," +
+                   t[0:t.find("*")].upper() + ",dst,offset);")
+        else:
+            printc('\tretval |= %(t)s_encodeBinary(&src->%(n)s,dst,offset);')
+    printc("\treturn retval;\n}\n")
+
+    # 6) DecodeBinary
+    printc('''UA_Int32 %(name)s_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, %(name)s * dst) {
+    \tUA_Int32 retval = UA_SUCCESS;''')
+    printc('\t'+name+'_init(dst);')
+    for n,t in membermap.iteritems():
+        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));')
+        else:
+            printc('\tCHECKED_DECODE(%(t)s_decodeBinary(src,offset,&dst->%(n)s), %(name)s_deleteMembers(dst));')
+    printc("\treturn retval;\n}\n")
+
+    # 7) Xml
+    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+    UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
+    UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)''')
     
-    # code _delete and _deleteMembers
-    print('UA_Int32 '+name+'_delete('+name+'''* p) {
+    # 8) Delete
+    printc('''UA_Int32 %(name)s_delete(%(name)s *p) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= '''+name+'''_deleteMembers(p);
+	retval |= %(name)s_deleteMembers(p);
 	retval |= UA_free(p);
-	return retval;
-}''', end='\n', file=fc)
+	return retval;\n}\n''')
 	
-    print("UA_Int32 "+name+"_deleteMembers(" + name + "* p) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
-    for n,t in valuemap.iteritems():
-        if t not in elementary_size:
-            if t.find("**") != -1:
-		print("\tretval |= UA_Array_delete((void***)&p->"+n+",p->"+n+"Size,UA_"+t[0:t.find("*")].upper()+"); p->"+n+" = UA_NULL;", end='\n', file=fc)
-            elif t.find("*") != -1:
-		print('\tretval |= UA_' + t[0:t.find("*")] + "_delete(p->"+n+");", end='\n', file=fc)
+    # 9) DeleteMembers
+    printc('''UA_Int32 %(name)s_deleteMembers(%(name)s *p) {
+    \tUA_Int32 retval = UA_SUCCESS;''')
+    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()+");")
             else:
-		print('\tretval |= UA_' + t + "_deleteMembers(&(p->"+n+"));", end='\n', file=fc)
-		
-    print("\treturn retval;\n}\n", end='\n', file=fc)
-
-	# code _init
-    print("UA_Int32 "+name+"_init(" + name + " * p) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
-    for n,t in valuemap.iteritems():
-		if t in elementary_size:
-			print('\tretval |= UA_'+t+'_init(&(p->'+n+'));', end='\n', file=fc)
-		else:
-			if t in enum_types:
-				print('\tretval |= UA_'+t+'_init(&(p->'+n+'));', end='\n', file=fc)
-			elif t.find("**") != -1:
-				print('\tp->'+n+'Size=0;', end='\n', file=fc)
-				print("\tp->"+n+"=UA_NULL;", end='\n', file=fc)
-			elif t.find("*") != -1:
-				print("\tp->"+n+"=UA_NULL;", end='\n', file=fc)
-			else:
-				print('\tretval |= UA_'+t+"_init(&(p->"+n+"));", end='\n', file=fc)
-    print("\treturn retval;\n}\n", end='\n', file=fc)
-
-	# code _new
-    print("UA_TYPE_METHOD_NEW_DEFAULT(" + name + ")", end='\n', file=fc)
-	# code _copy
-    print("UA_Int32 "+name+"_copy(" + name + " * src," + name + " * dst) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
-    for n,t in valuemap.iteritems():
-        if t in elementary_size:
-            print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
+		printc('\tretval |= %(t)s_deleteMembers(&p->%(n)s);')
+    printc("\treturn retval;\n}\n")
+
+    # 10) Init
+    printc('''UA_Int32 %(name)s_init(%(name)s *p) {
+    \tUA_Int32 retval = UA_SUCCESS;''')
+    for n,t in membermap.iteritems():
+        if t.find("*") != -1:
+            printc('\tp->%(n)sSize = 0;')
+            printc('\tp->%(n)s = UA_NULL;')
         else:
-            if t in enum_types:
-                print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
-            elif t.find("**") != -1:
-                print('\tretval |= UA_Int32_copy(&(src->'+n+'Size),&(dst->'+n+'Size)); // size of following array', end='\n', file=fc)
-		print("\tretval |= UA_Array_copy((void const* const*) (src->"+n+"), src->"+n+"Size," + "UA_" +
-                      t[0:t.find("*")].upper()+",(void***)&(dst->"+n+"));", end='\n', file=fc)
-            elif t.find("*") != -1:
-                print('\tretval |= UA_' + t[0:t.find("*")] + '_copy(src->' + n + ',dst->' + n + ');', end='\n', file=fc)
-            else:
-                print('\tretval |= UA_'+t+"_copy(&(src->"+n+"),&(dst->" + n + '));', end='\n', file=fc)
-    print("\treturn retval;\n}\n", end='\n', file=fc)
+            printc('\tretval |= %(t)s_init(&p->%(n)s);')
+    printc("\treturn retval;\n}\n")
+
+    # 11) New
+    printc("UA_TYPE_NEW_DEFAULT(%(name)s)")
+
+    # 12) Copy
+    printc('''UA_Int32 %(name)s_copy(const %(name)s *src,%(name)s *dst) {
+    \tif(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    \tUA_Int32 retval = UA_SUCCESS;''')
+    printc("\tmemcpy(dst, src, sizeof(%(name)s));")
+    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);")
+            continue
+        if not t in fixed_size: # there are members of variable size    
+            printc('\tretval |= %(t)s_copy(&src->%(n)s,&dst->%(n)s);')
+    printc("\treturn retval;\n}\n")
 	
-def createOpaque(element):
-    name = "UA_" + element.get("Name")
-    print("\n/** @name " + name + " */\n", file=fh)
-    for child in element:
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/** @brief " + child.text + " */", end='\n', file=fh)
-
-    print("typedef UA_ByteString " + name + ";", end='\n', file=fh)
-    print("UA_TYPE_METHOD_PROTOTYPES (" + name + ")", end='\n', file=fh)
-    print("UA_TYPE_METHOD_CALCSIZE_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_ENCODEBINARY_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DECODEBINARY_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DECODEXML_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_INIT_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_ByteString)", end='\n', file=fc)
-    print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
-
-ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
-tree = etree.parse(sys.argv[1])
-types = tree.xpath("/opc:TypeDictionary/*[not(self::opc:Import)]", namespaces=ns)
-
-fh = open(sys.argv[2] + ".hgen",'w');
-fc = open(sys.argv[2] + ".cgen",'w');
-
-print('''/**
+printh('''/**
  * @file '''+sys.argv[2]+'''.h
  *
  * @brief Autogenerated data types defined in the UA standard
@@ -289,13 +249,15 @@ print('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
 
-#ifndef OPCUA_H_
-#define OPCUA_H_
+#ifndef ''' + sys.argv[2].upper() + '''_H_
+#define ''' + sys.argv[2].upper() + '''_H_
 
-#include "ua_basictypes.h"
-#include "ua_namespace_0.h"''', end='\n', file=fh);
+#include "ua_types.h"
+#include "ua_types_encoding_binary.h"
+#include "ua_types_encoding_xml.h"
+#include "ua_namespace_0.h"\n''')
 
-print('''/**
+printc('''/**
  * @file '''+sys.argv[2]+'''.c
  *
  * @brief Autogenerated function implementations to manage the data types defined in the UA standard
@@ -304,7 +266,9 @@ print('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
  
-#include "''' + sys.argv[2] + '.h"', end='\n', file=fc);
+#include "''' + sys.argv[2] + '.h"\n')
+#include "ua_types_encoding_binary.h"
+#include "ua_util.h"
 
 # types for which we create a vector type
 arraytypes = set()
@@ -338,28 +302,30 @@ for element in types:
 		
 	if element.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedType":
 		createEnumerated(element)
-		printed_types.add(name)
+		existing_types.add(name)
 	elif element.tag == "{http://opcfoundation.org/BinarySchema/}StructuredType":
 		if printableStructuredType(element):
 			createStructured(element)
-			structured_types.append(name)
-			printed_types.add(name)
+			existing_types.add(name)
 		else: # the record contains types that were not yet detailed
 			deferred_types[name] = element
 			continue
 	elif element.tag == "{http://opcfoundation.org/BinarySchema/}OpaqueType":
 		createOpaque(element)
-		printed_types.add(name)
+		existing_types.add(name)
 
 for name, element in deferred_types.iteritems():
-	if name in plugin_types:
-		#execute plugin if registered
-		exec "ret = " + packageForType[name][0]+"."+packageForType[name][1]["functionCall"]
-		if ret == "default":
-			createStructured(element)
-	else:
-		createStructured(element)
+    if name in plugin_types:
+        #execute plugin if registered
+	exec "ret = " + packageForType[name][0]+"."+packageForType[name][1]["functionCall"]
+	if ret == "default":
+            createStructured(element)
+            existing_types.add(name)
+    else:
+	createStructured(element)
+        existing_types.add(name)
+
+printh('#endif')
 
-print('#endif /* OPCUA_H_ */', end='\n', file=fh)
 fh.close()
 fc.close()

+ 60 - 37
tools/generate_namespace.py

@@ -34,8 +34,8 @@ input_str = input_str.replace('\r','')
 rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
 f.close()
 
-fh = open(sys.argv[2] + ".hgen",'w')
-fc = open(sys.argv[2] + ".cgen",'w')
+fh = open(sys.argv[2] + ".h",'w')
+fc = open(sys.argv[2] + ".c",'w')
 
 print('''/**********************************************************
  * '''+sys.argv[2]+'''.hgen -- do not modify
@@ -44,10 +44,12 @@ print('''/**********************************************************
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  **********************************************************/
  
-#ifndef OPCUA_NAMESPACE_0_H_
-#define OPCUA_NAMESPACE_0_H_
+#ifndef ''' + sys.argv[2].upper() + '''_H_
+#define ''' + sys.argv[2].upper() + '''_H_
 
-#include "ua_basictypes.h"  // definition of UA_VTable and basic UA_Types
+#include "ua_util.h"
+#include "ua_types.h"  // definition of UA_VTable and basic UA_Types
+#include "ua_types_generated.h"
 
 /**
  * @brief maps namespace zero nodeId to index into UA_VTable
@@ -57,11 +59,13 @@ print('''/**********************************************************
  * @retval UA_ERR_INVALID_VALUE whenever ns0Id could not be mapped
  * @retval the corresponding index into UA_VTable
  */
-UA_Int32 UA_ns0ToVTableIndex(UA_Int32 id);
-extern UA_VTable UA_[]; 
+
+UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id);
+
+extern UA_VTable UA_; 
 
 static UA_Int32 phantom_delete(void * p) { return UA_SUCCESS; }
-extern UA_VTable UA_noDelete_[];
+extern UA_VTable UA_borrowed_;
 
 /**
  * @brief the set of possible indices into UA_VTable
@@ -77,11 +81,12 @@ print('''/**********************************************************
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  **********************************************************/
  
-#include "opcua.h"
+#include "''' + sys.argv[2] + '''.h"
 
-UA_Int32 UA_ns0ToVTableIndex(UA_Int32 ns0Id) {
+UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
 	UA_Int32 retval = UA_ERR_INVALID_VALUE;
-	switch (ns0Id) { ''', end='\n',file=fc)
+        if(id->namespace != 0) return retval;
+	switch (id->identifier.numeric) { ''', end='\n',file=fc)
 
 i = 0
 for row in rows:
@@ -104,7 +109,9 @@ print('''
     return retval;
 }
 
-UA_VTable UA_[] = {''', file=fc)
+UA_VTable UA_ = {
+\t.getTypeIndex = UA_ns0ToVTableIndex,
+\t.types = (UA_VTable_Entry[]){''', file=fc)
 
 for row in rows:
     if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
@@ -118,19 +125,28 @@ for row in rows:
 
     print('#define '+name.upper()+'_NS0 '+row[1], file=fh)
 
-    print("\t{" + row[1] + 
-          ",(UA_Int32(*)(void const*))"+name+"_calcSize" + 
-          ",(UA_Int32(*)(UA_ByteString const*,UA_Int32*,void*))"+name+ "_decodeBinary" +
-          ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
-          ",(UA_Int32(*)(XML_Stack*,XML_Attr*,void*,_Bool))"+ name + "_decodeXML" +
-          ",(UA_Int32(*)(void *))"+name+"_init"+
-          ",(UA_Int32(*)(void **))"+name+"_new"+
-          ",(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
-          ",(UA_Int32(*)(void *))"+name+"_delete"+
-          (",sizeof("+name+")" if (name != "UA_InvalidType") else ",0") +
-          ',(UA_Byte*)"'+name+'"},',end='\n',file=fc) 
-
-print("};\n\nUA_VTable UA_noDelete_[] = {", end='\n', file=fc)
+    print("\t{.typeId={UA_NODEIDTYPE_FOURBYTE,0,.identifier.numeric=" + row[1] +"}"+ 
+          ",.name=(UA_Byte*)&\""+name+"\""+
+          ",.new=(UA_Int32(*)(void **))"+name+"_new"+
+          ",.init=(UA_Int32(*)(void *))"+name+"_init"+
+          ",.copy=(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
+          ",.delete=(UA_Int32(*)(void *))"+name+"_delete"+
+          ",.deleteMembers=(UA_Int32(*)(void *))"+name+"_deleteMembers"+
+          ",.memSize=" + ("sizeof("+name+")" if (name != "UA_InvalidType") else "0") +
+          ",.encodings={(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeBinary" +
+          ",.encode=(UA_encode)"+name+ "_encodeBinary" +
+          ",.decode=(UA_decode)"+name+"_decodeBinary}"+
+          ",(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeXml" +
+          ",.encode=(UA_encode)"+name+ "_encodeXml" +
+          ",.decode=(UA_decode)"+name+"_decodeXml}"+
+          "}},",
+          end='\n',file=fc) 
+
+print('''}};
+
+UA_VTable UA_noDelete_ = {
+\t.getTypeIndex=UA_ns0ToVTableIndex,
+\t.types = (UA_VTable_Entry[]){''', end='\n', file=fc)
 
 for row in rows:
     if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
@@ -142,18 +158,25 @@ for row in rows:
     else:	
 	name = "UA_" + row[0]
 
-    print("\t{" + row[1] +
-          ",(UA_Int32(*)(void const*))"+name+"_calcSize" + 
-          ",(UA_Int32(*)(UA_ByteString const*,UA_Int32*,void*))"+name+ "_decodeBinary" +
-          ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
-          ",(UA_Int32(*)(XML_Stack*,XML_Attr*,void*,_Bool))" + name + "_decodeXML" +          
-          ",(UA_Int32(*)(void *))"+name+"_init"+
-          ",(UA_Int32(*)(void **))"+name+"_new"+
-          ",(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
-          ",(UA_Int32(*)(void *))phantom_delete"+
-          (",sizeof("+name+")" if (name != "UA_InvalidType") else ",0") +
-          ',(UA_Byte*)"'+name+'"},',end='\n',file=fc)
-print("};", end='\n', file=fc) 
+    print("\t{.typeId={UA_NODEIDTYPE_FOURBYTE,0,.identifier.numeric=" + row[1] +"}"+ 
+          ",.name=(UA_Byte*)&\""+name+"\""+
+          ",.new=(UA_Int32(*)(void **))"+name+"_new"+
+          ",.init=(UA_Int32(*)(void *))"+name+"_init"+
+          ",.copy=(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
+          ",.delete=(UA_Int32(*)(void *))phantom_delete"+
+          ",.deleteMembers=(UA_Int32(*)(void *))phantom_delete"+
+          ",.memSize=" + ("sizeof("+name+")" if (name != "UA_InvalidType") else "0") +
+          ",.encodings={(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeBinary" +
+          ",.encode=(UA_encode)"+name+ "_encodeBinary" +
+          ",.decode=(UA_decode)"+name+"_decodeBinary}"+
+          ",(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeXml" +
+          ",.encode=(UA_encode)"+name+ "_encodeXml" +
+          ",.decode=(UA_decode)"+name+"_decodeXml}"+
+          "}},",
+          end='\n',file=fc) 
+
+
+print("}};", end='\n', file=fc) 
 
 print('\n#endif /* OPCUA_NAMESPACE_0_H_ */', end='\n', file=fh)