Forráskód Böngészése

changes over the weekend

Julius Pfrommer 10 éve
szülő
commit
9549a87c62

+ 6 - 6
doc/Doxyfile.in

@@ -796,7 +796,7 @@ EXCLUDE                =
 # from the input.
 # The default value is: NO.
 
-EXCLUDE_SYMLINKS       = NO
+EXCLUDE_SYMLINKS       = YES
 
 # If the value of the INPUT tag contains directories, you can use the
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
@@ -1903,7 +1903,7 @@ ENABLE_PREPROCESSING   = YES
 # The default value is: NO.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
 # the macro expansion is limited to the macros specified with the PREDEFINED and
@@ -1925,7 +1925,7 @@ SEARCH_INCLUDES        = YES
 # preprocessor.
 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
-INCLUDE_PATH           =
+INCLUDE_PATH           = src
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -1943,7 +1943,7 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             =
+PREDEFINED             = 
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
@@ -1962,7 +1962,7 @@ EXPAND_AS_DEFINED      =
 # The default value is: YES.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-SKIP_FUNCTION_MACROS   = YES
+SKIP_FUNCTION_MACROS   = NO
 
 #---------------------------------------------------------------------------
 # Configuration options related to external references
@@ -2115,7 +2115,7 @@ COLLABORATION_GRAPH    = NO
 # The default value is: YES.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-GROUP_GRAPHS           = YES
+GROUP_GRAPHS           = NO
 
 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 # collaboration diagrams in a style similar to the OMG's Unified Modeling

+ 194 - 0
doc/DoxygenLayout.xml

@@ -0,0 +1,194 @@
+<doxygenlayout version="1.0">
+  <!-- Generated by doxygen 1.8.6 -->
+  <!-- Navigation index tabs for HTML output -->
+  <navindex>
+    <tab type="mainpage" visible="yes" title=""/>
+    <tab type="pages" visible="yes" title="" intro=""/>
+    <tab type="modules" visible="yes" title="" intro=""/>
+    <tab type="namespaces" visible="no" title="">
+      <tab type="namespacelist" visible="yes" title="" intro=""/>
+      <tab type="namespacemembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="classes" visible="no" title="">
+      <tab type="classlist" visible="yes" title="" intro=""/>
+      <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> 
+      <tab type="hierarchy" visible="yes" title="" intro=""/>
+      <tab type="classmembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="files" visible="yes" title="">
+      <tab type="filelist" visible="yes" title="" intro=""/>
+      <tab type="globals" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="examples" visible="no" title="" intro=""/>  
+  </navindex>
+
+  <!-- Layout definition for a class page -->
+  <class>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <inheritancegraph visible="$CLASS_GRAPH"/>
+    <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+    <memberdecl>
+      <nestedclasses visible="yes" title=""/>
+      <publictypes title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <publicslots title=""/>
+      <signals title=""/>
+      <publicmethods title=""/>
+      <publicstaticmethods title=""/>
+      <publicattributes title=""/>
+      <publicstaticattributes title=""/>
+      <protectedtypes title=""/>
+      <protectedslots title=""/>
+      <protectedmethods title=""/>
+      <protectedstaticmethods title=""/>
+      <protectedattributes title=""/>
+      <protectedstaticattributes title=""/>
+      <packagetypes title=""/>
+      <packagemethods title=""/>
+      <packagestaticmethods title=""/>
+      <packageattributes title=""/>
+      <packagestaticattributes title=""/>
+      <properties title=""/>
+      <events title=""/>
+      <privatetypes title=""/>
+      <privateslots title=""/>
+      <privatemethods title=""/>
+      <privatestaticmethods title=""/>
+      <privateattributes title=""/>
+      <privatestaticattributes title=""/>
+      <friends title=""/>
+      <related title="" subtitle=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <constructors title=""/>
+      <functions title=""/>
+      <related title=""/>
+      <variables title=""/>
+      <properties title=""/>
+      <events title=""/>
+    </memberdef>
+    <allmemberslink visible="yes"/>
+    <usedfiles visible="$SHOW_USED_FILES"/>
+    <authorsection visible="yes"/>
+  </class>
+
+  <!-- Layout definition for a namespace page -->
+  <namespace>
+    <briefdescription visible="yes"/>
+    <memberdecl>
+      <nestednamespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </namespace>
+
+  <!-- Layout definition for a file page -->
+  <file>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <includegraph visible="$INCLUDE_GRAPH"/>
+    <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+    <sourcelink visible="yes"/>
+    <memberdecl>
+      <classes visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection/>
+  </file>
+
+  <!-- Layout definition for a group page -->
+  <group>
+    <briefdescription visible="no"/>
+    <groupgraph visible="$GROUP_GRAPHS"/>
+    <detaileddescription title=""/>
+    <memberdecl>
+      <nestedgroups visible="yes" title=""/>
+      <dirs visible="yes" title=""/>
+      <files visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <pagedocs/>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+    </memberdef>
+    <authorsection visible="no"/>
+  </group>
+
+  <!-- Layout definition for a directory page -->
+  <directory>
+    <briefdescription visible="yes"/>
+    <directorygraph visible="yes"/>
+    <memberdecl>
+      <dirs visible="yes"/>
+      <files visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+  </directory>
+</doxygenlayout>

+ 1 - 0
doc/style/load-style.js

@@ -13,6 +13,7 @@ $( document ).ready(function() {
 	$("ul.tablist").css("margin-bottom", "0.5em");
 	$("li.current").addClass("active");
 	$(".contents").wrapInner("<div class='panel panel-default' style='margin-top:1em;'><div class='panel-body'></div></div>");
+	$(".contents").find("h2.groupheader:first").remove();
 
 	$("iframe").attr("scrolling", "yes");
 	

+ 36 - 40
examples/src/generateSam.c

@@ -1,11 +1,7 @@
-/*
- * xml2ns0.c
- *
- *  Created on: 21.04.2014
- *      Author: mrt
- */
-
 #include "ua_xml.h"
+#include "ua_namespace.h"
+#include "ua_namespace_xml.h"
+#include "ua_types_generated.h"
 #include <ctype.h> // tolower
 
 /** @brief we need a variable global to the module to make it possible for the visitors to access the namespace */
@@ -15,16 +11,16 @@ static Namespace* theNamespace;
 _Bool UA_VariableNode_isRoot(const UA_VariableNode* node) {
 	UA_Int32 i;
 	for (i = 0; i < node->referencesSize; i++ ) {
-		UA_Int32 refId = UA_NodeId_getIdentifier(&(node->references[i]->referenceTypeId));
-		UA_Int32 isInverse = node->references[i]->isInverse;
+		UA_Int32 refId = node->references[i].referenceTypeId.identifier.numeric;
+		UA_Int32 isInverse = node->references[i].isInverse;
 		if (isInverse && (refId == 47 || refId == 46)) {
 			Namespace_Entry_Lock* lock;
 			const UA_Node* parent;
 			UA_Int32 retval;
-			retval = Namespace_get(theNamespace, &(node->references[i]->targetId.nodeId),&parent,&lock);
+			retval = Namespace_get(theNamespace, &(node->references[i].targetId.nodeId),&parent,&lock);
 			if (retval != UA_SUCCESS || parent == UA_NULL || parent->nodeClass == UA_NODECLASS_VARIABLE) {
 				if (node->nodeId.identifier.numeric == 2007) {
-					printf("strange 2007 not included retval=%d,parentId=%d,parent=%p\n, ",retval,node->references[i]->targetId.nodeId.identifier.numeric,(void*)parent);
+					printf("strange 2007 not included retval=%d,parentId=%d,parent=%p\n, ",retval,node->references[i].targetId.nodeId.identifier.numeric,(void*)parent);
 				}
 				Namespace_Entry_Lock_release(lock);
 				return UA_FALSE;
@@ -46,7 +42,7 @@ _Bool UA_VariableNode_isRoot(const UA_VariableNode* node) {
 void sam_declareAttribute(UA_Node const * node) {
 	if (node->nodeClass == UA_NODECLASS_VARIABLE && UA_VariableNode_isRoot((UA_VariableNode*)node)) {
 		UA_VariableNode* vn = (UA_VariableNode*) node;
-		printf("\t%s " F_cls "; // i=%d\n", UA_[UA_ns0ToVTableIndex(vn->dataType.identifier.numeric)].name, LC_cls(node->browseName.name), node->nodeId.identifier.numeric);
+		printf("\t%s " F_cls "; // i=%d\n", UA_.types[UA_ns0ToVTableIndex(&vn->dataType)].name, LC_cls(node->browseName.name), node->nodeId.identifier.numeric);
 	}
 }
 
@@ -95,7 +91,7 @@ void sam_assignBuffer(UA_Node const * node) {
 void sam_attachToNamespace(UA_Node const * node) {
 	if (node != UA_NULL && node->nodeClass == UA_NODECLASS_VARIABLE) {
 		UA_VariableNode* vn = (UA_VariableNode*) node;
-		printf("\tsam_attach(ns,%d,%s,&sam." F_cls ");\n",node->nodeId.identifier.numeric,UA_[UA_ns0ToVTableIndex(vn->dataType.identifier.numeric)].name, LC_cls(vn->browseName.name));
+		printf("\tsam_attach(ns,%d,%s,&sam." F_cls ");\n",node->nodeId.identifier.numeric,UA_.types[UA_ns0ToVTableIndex(&vn->dataType)].name, LC_cls(vn->browseName.name));
 	}
 }
 
@@ -108,7 +104,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 +121,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,13 +133,13 @@ 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_UInt32* pos, UA_ByteString *dst) {
 	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,pos);
 	} else {
 		UA_Int32 nComp = 0;
 		if ((retval = Namespace_getNumberOfComponents(ns,id,&nComp)) == UA_SUCCESS) {
@@ -157,14 +153,14 @@ UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const
 	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);
 	}
@@ -192,25 +188,25 @@ pattern p[] = {
 };
 
 int main(int argc, char** argv) {
-	if (argc != 2) {
-		printf("usage: %s filename\n",argv[0]);
-	} else {
-		Namespace* ns;
-		if (Namespace_loadFromFile(&ns,0,"ROOT",argv[1]) != UA_SUCCESS) {
-			printf("error loading file {%s}\n", argv[1]);
-		} else {
-			theNamespace = ns;
-			for (pattern* pi = &p[0]; pi->s != UA_NULL || pi->v != UA_NULL; ++pi) {
-				if (pi->s) {
-					printf("%s",pi->s);
-				}
-				if (pi->v) {
-					Namespace_iterate(ns, pi->v);
-				}
-			}
-			// FIXME: crashes with a seg fault
-			// Namespace_delete(ns);
-		}
-	}
+	/* if (argc != 2) { */
+	/* 	printf("usage: %s filename\n",argv[0]); */
+	/* } else { */
+	/* 	Namespace* ns; */
+	/* 	if (Namespace_loadFromFile(&ns,0,"ROOT",argv[1]) != UA_SUCCESS) { */
+	/* 		printf("error loading file {%s}\n", argv[1]); */
+	/* 	} else { */
+	/* 		theNamespace = ns; */
+	/* 		for (pattern* pi = &p[0]; pi->s != UA_NULL || pi->v != UA_NULL; ++pi) { */
+	/* 			if (pi->s) { */
+	/* 				printf("%s",pi->s); */
+	/* 			} */
+	/* 			if (pi->v) { */
+	/* 				Namespace_iterate(ns, pi->v); */
+	/* 			} */
+	/* 		} */
+	/* 		// FIXME: crashes with a seg fault */
+	/* 		// Namespace_delete(ns); */
+	/* 	} */
+	/* } */
 	return 0;
 }

+ 1 - 1
examples/src/networklayer.h

@@ -1,7 +1,7 @@
 #ifndef NETWORKLAYER_H_
 #define NETWORKLAYER_H_
 
-#include "opcua.h"
+#include "ua_types.h"
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 #include "ua_list.h"

+ 1 - 1
examples/src/opcuaServerACPLT.c

@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include <memory.h>
 
-#include "opcua.h"
+#include "ua_types.h"
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 #include "networklayer.h"

+ 4 - 2
examples/src/xml2ns0.c

@@ -3,7 +3,9 @@
 #include "ua_types_generated.h"
 #include "ua_namespace.h"
 #include "ua_xml.h"
-#include "ua_xml_namespace.h"
+#include "ua_namespace_xml.h"
+#include "ua_types_encoding_xml.h"
+#include "ua_util.h"
 
 typedef UA_Int32 (*XML_Stack_Loader) (char* buf, int len);
 
@@ -20,7 +22,7 @@ UA_Int32 Namespace_loadXml(Namespace **ns,UA_UInt32 nsid,const char* rootName, X
 	UA_NodeSet_init(&n, 0);
 	*ns = n.ns;
 
-	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);
 	XML_SetElementHandler(parser, XML_Stack_startElement, XML_Stack_endElement);

+ 2 - 1
src/Makefile.am

@@ -5,8 +5,9 @@ lib_LTLIBRARIES = libopen62541.la
 lib_LTLIBRARIES: generate_types generate_namespace_0
 libopen62541_la_LDFLAGS = -avoid-version -no-undefined
 libopen62541_la_SOURCES = ua_types.c \
-						  ua_types_generated.c \
+						  ua_util.c \
 						  ua_types_encoding_binary.c \
+						  ua_types_generated.c \
 						  ua_types_encoding_xml.c \
 						  ua_namespace_0.c \
 						  util/ua_list.c \

+ 7 - 2
src/ua_xml_namespace.h

@@ -1,5 +1,9 @@
-#include "ua_namespace.h"
+#ifndef __UA_NAMESPACE_XML_H
+#define __UA_NAMESPACE_XML_H
+
 #include "ua_xml.h"
+#include "ua_types_generated.h"
+#include "ua_namespace.h"
 
 void print_node(UA_Node const * node);
 UA_Int32 UA_NodeSetAlias_init(UA_NodeSetAlias* p);
@@ -20,7 +24,7 @@ typedef struct UA_NodeSet {
 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_NodeSet_decodeXmlFromStack(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart);
 
 UA_Int32 UA_ExpandedNodeId_copycstring(cstring src, UA_ExpandedNodeId* dst, UA_NodeSetAliases* aliases);
 
@@ -33,3 +37,4 @@ UA_Int32 UA_ExpandedNodeId_copycstring(cstring src, UA_ExpandedNodeId* dst, UA_N
  */
 UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char* rootName,const char* fileName);
 
+#endif /* __UA_NAMESPACE_XML_H */

+ 51 - 33
src/ua_types.c

@@ -6,7 +6,7 @@
 #include <sys/time.h>
 #include "ua_util.h"
 #include "ua_types.h"
-#include "ua_types_generated.h"
+#include "ua_types_encoding_binary.h"
 #include "ua_namespace_0.h"
 
 /************/
@@ -149,10 +149,12 @@ UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2) {
 	}
 	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;
@@ -167,6 +169,7 @@ void UA_String_printx(char const *label, const UA_String *string) {
 		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) {
@@ -234,10 +237,14 @@ UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String *timeString) {
 
 /* Guid */
 UA_TYPE_DELETE_DEFAULT(UA_Guid)
-UA_Int32 UA_Guid_deleteMembers(UA_Guid *p) { return UA_SUCCESS; }
+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;
@@ -246,6 +253,7 @@ UA_Int32 UA_Guid_init(UA_Guid *p) {
 	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;
@@ -255,19 +263,27 @@ UA_Int32 UA_Guid_copy(UA_Guid const *src, UA_Guid *dst) {
 }
 
 /* ByteString */
-UA_TYPE_NEW_DEFAULT(UA_ByteString)
+UA_TYPE_AS(UA_ByteString, UA_String)
 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); }
+	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); }
+	UA_String_printf(label, (UA_String *)string);
+}
+
 void UA_ByteString_printx(char *label, const UA_ByteString *string) {
-	UA_String_printx(label, (UA_String *)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_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_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;
@@ -285,7 +301,8 @@ 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); }
+	return (id->namespace == 0 && id->identifier.numeric <= UA_DIAGNOSTICINFO);
+}
 
 UA_TYPE_DELETE_DEFAULT(UA_NodeId)
 UA_Int32 UA_NodeId_deleteMembers(UA_NodeId *p) {
@@ -322,21 +339,18 @@ void UA_NodeId_printf(char *label, const UA_NodeId *node) {
 	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}}",
@@ -345,7 +359,6 @@ void UA_NodeId_printf(char *label, const UA_NodeId *node) {
 			   8,
 			   (char *)(node->identifier.guid.data4));
 		break;
-
 	default:
 		printf("ups! shit happens");
 		break;
@@ -365,13 +378,10 @@ UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2) {
 			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);
 	}
@@ -550,6 +560,7 @@ UA_Int32 UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
 	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);
@@ -557,6 +568,7 @@ UA_Int32 UA_ExtensionObject_init(UA_ExtensionObject *p) {
 	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;
@@ -574,6 +586,7 @@ UA_Int32 UA_DataValue_deleteMembers(UA_DataValue *p) {
 	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;
@@ -585,8 +598,8 @@ UA_Int32 UA_DataValue_init(UA_DataValue *p) {
 	UA_Variant_init(&p->value);
 	return UA_SUCCESS;
 }
-UA_TYPE_NEW_DEFAULT(UA_DataValue)
 
+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
@@ -623,12 +636,12 @@ UA_Int32 UA_Variant_init(UA_Variant *p) {
 }
 
 UA_TYPE_NEW_DEFAULT(UA_Variant)
-
 UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
-	UA_Int32 retval = UA_SUCCESS;
+	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);
+	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);
@@ -644,7 +657,7 @@ UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
 
 	if(src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
 		retval |= UA_Array_copy(src->arrayDimensions, src->arrayDimensionsLength,
-								UA_INT32, (void**)&dst->arrayDimensions);
+		                        UA_INT32, (void **)&dst->arrayDimensions);
 	}
 	return retval;
 }
@@ -653,7 +666,7 @@ UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type_id, const void *
 	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;
+	v->data   = (void *)value;
 	return UA_SUCCESS;
 }
 
@@ -735,18 +748,23 @@ UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo
 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;
 }
@@ -757,11 +775,11 @@ UA_Int32 UA_InvalidType_new(UA_InvalidType **p) {
 
 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
+	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;
+			cp     += UA_.types[type].memSize;
 		}
 	}
 	UA_free(p);
@@ -786,10 +804,10 @@ 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 retval = UA_SUCCESS;
-	char *cp = (char *)p; // so compilers allow pointer arithmetic
-	for(UA_Int32 i=0;i<noElements && retval == UA_SUCCESS;i++) {
+	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;
+		cp     += UA_.types[type].memSize;
 	}
 	return retval;
 }
@@ -800,13 +818,13 @@ UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void
 
 	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;
+
+	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;
+		csrc   += UA_.types[type].memSize;
+		cdst   += UA_.types[type].memSize;
 	}
 	return retval;
 }

+ 83 - 49
src/ua_types.h

@@ -3,6 +3,34 @@
 
 #include <stdint.h>
 
+/**
+ * @defgroup types Datatypes
+ *
+ * @brief This module describes the datatypes used in OPC UA. There is a
+ * division into built-in datatypes (integers, strings, etc.) and more complex
+ * datatypes that are comprise of built-in datatypes (structs defined in the OPC
+ * UA standard).
+ *
+ * All datatypes follow the same schema in the naming of relevant functions.
+ *
+ * - <type>_init: Sets all values to a "safe" standard. For example, if the
+ *     datatype contains a string-element, its size will be set to zero.
+ *
+ * - <type>_new: Allocates the memory for the type and runs <type>_init on the
+ *     returned pointer.
+ *
+ * - <type>_copy: Copies a datatype. This performs a deep copy that iterates
+ *    over the members.
+ *
+ * - <type>_delete: Frees the memory where the datatype was stored.
+ *
+ * - <type>_deleteMembers: Frees the memory of dynamically sized members (e.g. a
+     string) of a datatype. This is useful when the datatype was allocated on
+     the stack, whereas the dynamically sized members is heap-allocated.
+ *
+ * @{
+ */
+
 /* Function return values */
 #define UA_SUCCESS 0
 #define UA_NO_ERROR UA_SUCCESS
@@ -143,12 +171,12 @@ 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_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 */
@@ -207,7 +235,7 @@ typedef void UA_InvalidType;
 /* Functions */
 /*************/
 
-#define UA_TYPE_PROTOTYPES(TYPE)      \
+#define UA_TYPE_PROTOTYPES(TYPE)             \
     UA_Int32 TYPE##_new(TYPE **p);           \
     UA_Int32 TYPE##_init(TYPE * p);          \
     UA_Int32 TYPE##_delete(TYPE * p);        \
@@ -294,12 +322,13 @@ UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 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.
+UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_Int32 type, const void *data);
+UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_Int32 type, UA_Int32 arrayLength, const void *data);
 
 /* Array operations */
 UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_Int32 type);
@@ -314,7 +343,7 @@ UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_Int32 type, void
 /**********/
 
 /* @brief Returns the size of the encoded element.*/
-typedef UA_Int32 (*UA_calcSize)(const void * p);
+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);
@@ -324,45 +353,48 @@ 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_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_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_Boolean  dynMembers;   // does the type contain members that are dynamically
+	                          // allocated (strings, ..)? Otherwise, the size on
+	                          // the wire == size in memory.
 	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_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_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)         \
@@ -377,7 +409,7 @@ typedef struct UA_VTable {
 		return TYPE_AS##_init((TYPE_AS *)p); \
 	}
 
-#define UA_TYPE_DELETE_DEFAULT(TYPE)	   \
+#define UA_TYPE_DELETE_DEFAULT(TYPE)       \
     UA_Int32 TYPE##_delete(TYPE *p) {      \
 		UA_Int32 retval = UA_SUCCESS;      \
 		retval |= TYPE##_deleteMembers(p); \
@@ -395,23 +427,25 @@ typedef struct UA_VTable {
     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_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_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)
+#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)
+
+/// @} /* end of group */
 
 #endif /* UA_TYPES_H_ */

+ 6 - 8
src/ua_types_encoding_binary.c

@@ -55,7 +55,7 @@ UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_
 #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 ) { \
+		if((UA_Int32) (*offset + TYPE##_calcSizeBinary(src)) > dst->length ) { \
 			return UA_ERR_INVALID_VALUE;                                                \
 		} else {                                                                        \
 			CODE                                                                        \
@@ -67,7 +67,7 @@ UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_
 #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 ) { \
+		if((UA_Int32) (*offset + TYPE##_calcSizeBinary(UA_NULL)) > src->length ) { \
 			return UA_ERR_INVALID_VALUE;                                                \
 		} else {                                                                        \
 			CODE                                                                        \
@@ -258,8 +258,7 @@ UA_Int32 UA_String_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_
 }
 
 /* DateTime */
-UA_TYPE_ENCODEBINARY_AS(UA_DateTime, UA_Int64)
-UA_TYPE_DECODEBINARY_AS(UA_DateTime, UA_Int64)
+UA_TYPE_BINARY_ENCODING_AS(UA_DateTime, UA_Int64)
 
 /* Guid */
 UA_Int32 UA_Guid_calcSizeBinary(UA_Guid const *p) {
@@ -285,12 +284,10 @@ UA_TYPE_DECODEBINARY(UA_Guid,
 						 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)
+UA_TYPE_BINARY_ENCODING_AS(UA_ByteString, UA_String)
 
 /* XmlElement */
-UA_TYPE_ENCODEBINARY_AS(UA_XmlElement, UA_String)
-UA_TYPE_DECODEBINARY_AS(UA_XmlElement, UA_String)
+UA_TYPE_BINARY_ENCODING_AS(UA_XmlElement, UA_String)
 
 /* NodeId */
 UA_Int32 UA_NodeId_calcSizeBinary(UA_NodeId const *p) {
@@ -456,6 +453,7 @@ UA_Int32 UA_ExpandedNodeId_decodeBinary(UA_ByteString const *src, UA_UInt32 *off
 }
 
 /* StatusCode */
+UA_TYPE_BINARY_ENCODING_AS(UA_StatusCode, UA_UInt32)
 
 /* QualifiedName */
 UA_Int32 UA_QualifiedName_calcSizeBinary(UA_QualifiedName const *p) {

+ 57 - 24
src/ua_types_encoding_binary.h

@@ -4,37 +4,66 @@
 #include "ua_util.h"
 #include "ua_types.h"
 
+/**
+ * @ingroup types
+ * @defgroup encoding Datatype Encoding
+ *
+ * @brief Datatypes can have several encodings. The methods defined for
+ * encodings and their signature are fixed.
+ *
+ * - CalcSize: Returns the size of the (encoded) variable in bytes. This
+ *    function is mainly used to allocate the bytestring into which the encoding
+ *    is done.
+ *
+ * - Encode: Encodes a variable into a bytestring.
+ *
+ * - Decode: Decodes a variable stored in a bytestring. It is assumed that the
+ *   input variable (dst) is allocated in memory, but not its dynamically sized
+ *   members.
+ */
+
+/**
+ * @ingroup encoding
+ * @defgroup encoding_binary Binary Encoding
+ *
+ * @brief Functions for binary en- and decoding of built-in datatypes as defined
+ * in the standard.
+ *
+ * @{
+ */
+
 /* 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)
+		retval |= DECODE;                     \
+		if(retval != UA_SUCCESS) {            \
+			CLEAN_UP;                         \
+			return retval;                    \
+		} } while(0)
 
-#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_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_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_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_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_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);
+#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)
@@ -71,9 +100,13 @@ UA_TYPE_BINARY_ENCODING(UA_InvalidType)
 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);
+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);
+UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements, UA_Int32 type,
+                               void **dst);
+
+/// @} /* end of group */
 
 #endif /* UA_TYPES_ENCODING_BINARY_H_ */

+ 308 - 9
src/ua_types_encoding_xml.c

@@ -1,5 +1,6 @@
 #include "ua_types_encoding_xml.h"
 #include "ua_util.h"
+#include "ua_namespace_0.h"
 #include "ua_xml.h"
 
 /* Boolean */
@@ -11,6 +12,7 @@ UA_Int32 UA_Boolean_copycstring(cstring src, UA_Boolean *dst) {
 	return UA_SUCCESS;
 }
 
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_Boolean)
 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));
@@ -24,6 +26,8 @@ UA_Int32 UA_Boolean_decodeXML(XML_Stack *s, XML_Attr *attr, UA_Boolean *dst, _Bo
 	return UA_SUCCESS;
 }
 
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_Boolean)
+
 /* SByte */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_SByte)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_SByte)
@@ -37,7 +41,30 @@ 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)
+
+UA_Int32 UA_Int16_copycstring(cstring src, UA_Int16 *dst) {
+	*dst = atoi(src);
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_UInt16_copycstring(cstring src, UA_UInt16 *dst) {
+	*dst = atoi(src);
+	return UA_SUCCESS;
+}
+
+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) {
+			UA_Int16_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void *)dst;
+		}
+		UA_Int16_copycstring((cstring)attr[1], dst);
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_Int16)
 
 /* UInt16 */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_UInt16)
@@ -47,7 +74,19 @@ 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)
+
+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) {
+			UA_Int32_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void *)dst;
+		}
+		*dst = atoi(attr[1]);
+	}
+	return UA_SUCCESS;
+}
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_Int32)
 
 /* UInt32 */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_UInt32)
@@ -77,7 +116,41 @@ 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)
+
+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) {
+		if(dst == UA_NULL) {
+			UA_String_new(&dst);
+			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_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
+		for(i = 0;attr[i];i += 2) {
+			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]);
+		}
+	} else {
+		switch(s->parent[s->depth - 1].activeChild) {
+		case 0:
+			if(dst != UA_NULL && dst->data != UA_NULL && dst->length == -1)
+				dst->length = strlen((char const *)dst->data);
+			break;
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_String)
 
 /* DateTime */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DateTime)
@@ -102,12 +175,84 @@ 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)
+
+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) {
+		if(dst == UA_NULL) {
+			UA_NodeId_new(&dst);
+			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_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
+		for(i = 0; attr[i]; i += 2) {
+		if(0 == strncmp("Namespace", attr[i], strlen("Namespace")))
+			dst->namespace = atoi(attr[i + 1]);
+		else if(0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
+		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]);
+		}
+	} else {
+		if(s->parent[s->depth - 1].activeChild == 2)
+			UA_NodeId_copycstring((cstring)((UA_String *)attr)->data, dst, s->aliases);
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_NodeId)
 
 /* ExpandedNodeId */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ExpandedNodeId)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ExpandedNodeId)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ExpandedNodeId)
+
+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) {
+		if(dst == UA_NULL) {
+			UA_ExpandedNodeId_new(&dst);
+			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_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_decodeXmlFromStack, UA_STRING, UA_NULL);
+		XML_Stack_handleTextAsElementOf(s, "Data", 3);
+
+		// set attributes
+		for(i = 0; attr[i]; i += 2) {
+		if(0 == strncmp("Namespace", attr[i], strlen("Namespace")))
+			UA_UInt16_copycstring((cstring)attr[i + 1], &(dst->nodeId.namespace));
+		else if(0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
+		UA_NodeId_copycstring((cstring)attr[i + 1], &(dst->nodeId), s->aliases);
+		} 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]);
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_ExpandedNodeId)
 
 /* StatusCode */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_StatusCode)
@@ -116,21 +261,124 @@ UA_Int32 UA_StatusCode_decodeXML(XML_Stack *s, XML_Attr *attr, UA_StatusCode *ds
 	DBG_VERBOSE(printf("UA_StatusCode_decodeXML entered with dst=%p,isStart=%d\n", (void * )dst, isStart));
 	return UA_ERR_NOT_IMPLEMENTED;
 }
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_StatusCode)
 
 /* QualifiedName */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_QualifiedName)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_QualifiedName)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_QualifiedName)
+
+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) {
+		if(dst == UA_NULL) {
+			UA_QualifiedName_new(&dst);
+			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_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);
+
+		// set attributes
+		for(i = 0;attr[i];i += 2) {
+			if(0 == strncmp("NamespaceIndex", attr[i], strlen("NamespaceIndex")))
+				dst->namespaceIndex = atoi(attr[i + 1]);
+			else if(0 == strncmp("Name", attr[i], strlen("Name")))
+				UA_String_copycstring(attr[i + 1], &(dst->name));
+			else
+				perror("Unknown attribute");
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_QualifiedName)
 
 /* LocalizedText */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_LocalizedText)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_LocalizedText)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_LocalizedText)
+
+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) {
+		if(dst == UA_NULL) {
+			UA_LocalizedText_new(&dst);
+			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_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
+		for(i = 0;attr[i];i += 2) {
+			if(0 == strncmp("Text", attr[i], strlen("Text"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->text));
+				dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+			} else if(0 == strncmp("Locale", attr[i], strlen("Locale"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->locale));
+				dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
+			} else
+				perror("Unknown attribute");
+		}
+	} else {
+		switch(s->parent[s->depth - 1].activeChild) {
+		case 0:
+			dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+			break;
+
+		case 1:
+			dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
+			break;
+
+		default:
+			break;
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_LocalizedText)
 
 /* ExtensionObject */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ExtensionObject)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ExtensionObject)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ExtensionObject)
+
+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;
+
+	if(isStart) {
+		// create a new object if called with UA_NULL
+		if(dst == UA_NULL) {
+			UA_ExtensionObject_new(&dst);
+			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, "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) {
+			{
+				DBG_ERR(XML_Stack_print(s));
+				DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
+			}
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_ExtensionObject)
 
 /* DataValue */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DataValue)
@@ -140,7 +388,58 @@ 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)
+
+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;
+
+	if(isStart) {
+		// create a new object if called with UA_NULL
+		if(dst == UA_NULL) {
+			UA_Variant_new(&dst);
+			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, "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) {
+			{
+				DBG_ERR(XML_Stack_print(s));
+				DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
+			}
+		}
+	} 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));
+			dst->arrayLength  = array->size;
+			dst->data         = array->elements;
+			dst->vt = &UA_.types[UA_EXTENSIONOBJECT];
+			dst->encodingMask = UA_EXTENSIONOBJECT_NS0 & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
+		} else if(s->parent[s->depth - 1].activeChild == 1 && attr != UA_NULL ) {  // LocalizedText
+			UA_TypedArray *array = (UA_TypedArray *)attr;
+			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_.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;
+		}
+	}
+	return UA_SUCCESS;
+}
+
+UA_TYPE_ENCODEXML_FROM_BYTESTRING(UA_Variant)
 
 /* DiagnosticInfo */
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_DiagnosticInfo)

+ 12 - 2
src/ua_types_encoding_xml.h

@@ -29,11 +29,21 @@
 	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) { \
+																		\
+ 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;\
+     return UA_ERR_NOT_IMPLEMENTED; \
  }
 
+#define UA_TYPE_ENCODEXML_FROM_BYTESTRING(TYPE) \
+	UA_Int32 TYPE##_decodeXml(UA_ByteString *src, UA_UInt32 *offset, TYPE *dst) { \
+	/* // Init Stack here \
+	UA_Stack *stack; \
+	UA_Attr *attr; \
+	TYPE##decodeXmlFromStack(stack, attr, dst, UA_TRUE); \
+	*/ \
+	return UA_ERR_NOT_IMPLEMENTED; \
+} 
 
 UA_TYPE_XML_ENCODING(UA_Boolean)
 UA_TYPE_XML_ENCODING(UA_SByte)

+ 30 - 0
src/ua_util.c

@@ -0,0 +1,30 @@
+#include "ua_util.h"
+
+void const *UA_alloc_lastptr;
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}

+ 5 - 29
src/ua_util.h

@@ -20,41 +20,17 @@
 # endif
 #endif
 
-
 /* Global Variables */
 extern UA_ByteString UA_ByteString_securityPoliceNone;
 
 /* Heap memory functions */
 #define UA_NULL ((void *)0)
-extern void const *UA_alloc_lastptr;
+UA_Int32 _UA_free(void *ptr, char *pname, char *f, UA_Int32 l);
+UA_Int32 _UA_alloc(void **ptr, UA_Int32 size, char *pname, char *sname, char *f, UA_Int32 l);
+UA_Int32 UA_memcpy(void *dst, void const *src, UA_Int32 size);
+UA_Int32 UA_VTable_isValidType(UA_Int32 type);
+
 #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_ */

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 496 - 738
src/ua_xml.c


+ 44 - 39
src/ua_xml.h

@@ -1,21 +1,21 @@
-#ifndef __UA_XML_H__
-#define __UA_XML_H__
+#ifndef __UA_XML_H
+#define __UA_XML_H
 
 #include <expat.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h> // strlen
-#include <ctype.h> // isspace
+#include <ctype.h>  // isspace
 #include <unistd.h> // read
 
 #include "ua_types.h"
 
 struct XML_Stack;
-typedef char const * const XML_Attr;
-typedef char const * cstring;
+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);
+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 {
@@ -32,51 +32,50 @@ typedef struct UA_NodeSetAliases {
 UA_TYPE_PROTOTYPES(UA_NodeSetAliases)
 
 typedef struct XML_child {
- cstring     name;
- UA_Int32    length;
- UA_Int32    type;
- XML_decoder elementHandler;
- void       *obj;
+	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];
+	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
+	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);
+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);
+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);
 
 /** @brief an object to hold a typed array */
 typedef struct UA_TypedArray {
-	UA_Int32 size;
-	UA_VTable_Entry* vt;
-	void* elements;
+	UA_Int32         size;
+	UA_VTable_Entry *vt;
+	void *elements;
 } UA_TypedArray;
 
 /** @brief init typed array with size=-1 and an UA_INVALIDTYPE */
-UA_Int32 UA_TypedArray_init(UA_TypedArray* p);
+UA_Int32 UA_TypedArray_init(UA_TypedArray *p);
 
 /** @brief allocate memory for the array header only */
-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_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, UA_Boolean isStart);
 
 /** @brief add a reference to a handler (@see XML_Stack_addChildHandler) for text data
  *
@@ -91,13 +90,13 @@ UA_Int32 UA_TypedArray_decodeXML(XML_Stack* s, XML_Attr* attr, UA_TypedArray* ds
  * We would add two (@ref XML_Stack_addChildHandler), one for Locale (index 0) and one for Text (index 1),
  * both to be handled by (@ref UA_String_decodeXML) with elements "Data" and "Length". To handle the
  * abbreviation we add
- *   	XML_Stack_handleTextAsElementOf(s,"Data",1)
+ *      XML_Stack_handleTextAsElementOf(s,"Data",1)
  *
  * @param[in] s the stack
  * @param[in] textAttrib the name of the element of the handler at position textAttribIdx
  * @param[in] textAttribIdx the index of the handler
  */
-void XML_Stack_handleTextAsElementOf(XML_Stack* p, cstring textAttrib, unsigned int textAttribIdx);
+void XML_Stack_handleTextAsElementOf(XML_Stack *p, cstring textAttrib, unsigned int textAttribIdx);
 
 /** @brief make a handler known to the XML-stack on the current level
  *
@@ -111,11 +110,17 @@ void XML_Stack_handleTextAsElementOf(XML_Stack* p, cstring textAttrib, unsigned
  * @param[in] type the open62541-type of the element, UA_INVALIDTYPE if not in the VTable
  * @param[out] dst the address of the object for the data, handlers will allocate object if UA_NULL
  */
-void XML_Stack_addChildHandler(XML_Stack* p, cstring name, UA_Int32 nameLength, XML_decoder handler, UA_Int32 type, void* dst);
+void XML_Stack_addChildHandler(XML_Stack *p, cstring name, UA_Int32 nameLength, XML_decoder handler, UA_Int32 type,
+                               void *dst);
 
-void XML_Stack_startElement(void * data, const char *el, const char **attr);
+void XML_Stack_startElement(void *data, const char *el, const char **attr);
 UA_Int32 XML_isSpace(cstring s, int len);
-void XML_Stack_handleText(void * data, const char *txt, int len);
+void XML_Stack_handleText(void *data, const char *txt, int len);
 void XML_Stack_endElement(void *data, const char *el);
 
+
+UA_Int32 UA_Text_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_Byte **dst, _Bool isStart);
+UA_Int32 UA_NodeId_copycstring(cstring src, UA_NodeId *dst, UA_NodeSetAliases *aliases);
+UA_Int32 UA_TypedArray_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_TypedArray *dst, _Bool isStart);
+
 #endif // __UA_XML_H__

+ 0 - 1
tools/generate_builtin.py

@@ -101,7 +101,6 @@ def createOpaque(element):
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
 UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)\n''')
 
-    
 def createStructured(element):
     name = "UA_" + element.get("Name")
 

+ 57 - 50
tools/generate_namespace.py

@@ -1,4 +1,5 @@
 from __future__ import print_function
+import inspect
 import sys
 import platform
 import getpass
@@ -28,6 +29,22 @@ exclude_types = set(["Number", "Integer", "UInteger", "Enumeration",
 	"ConditionVariableType", "MultiStateValueDiscreteType", "OptionSetType", "ArrayItemType",
 	"YArrayItemType", "XYArrayItemType", "ImageItemType", "CubeItemType", "NDimensionArrayItemType"])
 
+fixed_size = ['UA_DeadbandType', 'UA_DataChangeTrigger', 'UA_Guid', 'UA_ApplicationType',
+              'UA_ComplexNumberType', 'UA_EnumeratedTestType', 'UA_BrowseResultMask',
+              'UA_TimeZoneDataType', 'UA_NodeClass', 'UA_IdType', 'UA_ServiceCounterDataType',
+              'UA_Float', 'UA_ModelChangeStructureVerbMask', 'UA_EndpointConfiguration',
+              'UA_NodeAttributesMask', 'UA_DataChangeFilter', 'UA_StatusCode', 'UA_MonitoringFilterResult',
+              'UA_OpenFileMode', 'UA_SecurityTokenRequestType', 'UA_ServerDiagnosticsSummaryDataType',
+              'UA_ElementOperand', 'UA_AggregateConfiguration', 'UA_UInt64', 'UA_FilterOperator',
+              'UA_ReadRawModifiedDetails', 'UA_ServerState', 'UA_FilterOperand', 'UA_SubscriptionAcknowledgement',
+              'UA_AttributeWriteMask', 'UA_SByte', 'UA_Int32', 'UA_Range', 'UA_Byte', 'UA_TimestampsToReturn',
+              'UA_UserTokenType', 'UA_Int16', 'UA_XVType', 'UA_AggregateFilterResult', 'UA_Boolean',
+              'UA_MessageSecurityMode', 'UA_AxisScaleEnumeration', 'UA_PerformUpdateType', 'UA_UInt16',
+              'UA_NotificationData', 'UA_DoubleComplexNumberType', 'UA_HistoryUpdateType', 'UA_MonitoringFilter',
+              'UA_NodeIdType', 'UA_BrowseDirection', 'UA_SamplingIntervalDiagnosticsDataType', 'UA_UInt32',
+              'UA_ChannelSecurityToken', 'UA_RedundancySupport', 'UA_MonitoringMode', 'UA_HistoryReadDetails',
+              'UA_ExceptionDeviationFormat', 'UA_ComplianceLevel', 'UA_DateTime', 'UA_Int64', 'UA_Double']
+
 f = open(sys.argv[1])
 input_str = f.read() + "\nInvalidType,0,DataType"
 input_str = input_str.replace('\r','')
@@ -36,21 +53,23 @@ f.close()
 
 fh = open(sys.argv[2] + ".h",'w')
 fc = open(sys.argv[2] + ".c",'w')
+def printh(string):
+    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fh)
+
+def printc(string):
+    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fc)
 
-print('''/**********************************************************
+printh('''/**********************************************************
  * '''+sys.argv[2]+'''.hgen -- do not modify
  **********************************************************
  * Generated from '''+sys.argv[1]+''' with script '''+sys.argv[0]+'''
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
- **********************************************************/
- 
+ **********************************************************/\n 
 #ifndef ''' + sys.argv[2].upper() + '''_H_
-#define ''' + sys.argv[2].upper() + '''_H_
-
+#define ''' + sys.argv[2].upper() + '''_H_\n
 #include "ua_util.h"
 #include "ua_types.h"  // definition of UA_VTable and basic UA_Types
-#include "ua_types_generated.h"
-
+#include "ua_types_generated.h"\n
 /**
  * @brief maps namespace zero nodeId to index into UA_VTable
  *
@@ -58,35 +77,29 @@ print('''/**********************************************************
  *
  * @retval UA_ERR_INVALID_VALUE whenever ns0Id could not be mapped
  * @retval the corresponding index into UA_VTable
- */
-
-UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id);
-
-extern UA_VTable UA_; 
-
+ */\n
+UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id);\n
+extern const UA_VTable UA_;\n
 static UA_Int32 phantom_delete(void * p) { return UA_SUCCESS; }
-extern UA_VTable UA_borrowed_;
-
+extern const UA_VTable UA_borrowed_;\n
 /**
  * @brief the set of possible indices into UA_VTable
  *
  * Enumerated type to define the types that the open62541 stack can handle
  */
-enum UA_VTableIndex_enum {''', end='\n', file=fh)
+enum UA_VTableIndex_enum {''')
 
-print('''/**********************************************************
+printc('''/**********************************************************
  * '''+sys.argv[2]+'''.cgen -- do not modify
  **********************************************************
  * Generated from '''+sys.argv[1]+''' with script '''+sys.argv[0]+'''
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
- **********************************************************/
- 
-#include "''' + sys.argv[2] + '''.h"
-
+ **********************************************************/\n
+#include "''' + sys.argv[2] + '''.h"\n
 UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
 	UA_Int32 retval = UA_ERR_INVALID_VALUE;
         if(id->namespace != 0) return retval;
-	switch (id->identifier.numeric) { ''', end='\n',file=fc)
+	switch (id->identifier.numeric) {''')
 
 i = 0
 for row in rows:
@@ -99,19 +112,15 @@ for row in rows:
     else:
         name = "UA_" + row[0]
 	
-    print("\t"+name.upper()+" = "+str(i)+",", file=fh)
-    print('\tcase '+row[1]+': retval='+name.upper()+'; break; //'+row[2], file=fc)
+    printh("\t"+name.upper()+" = "+str(i)+",")
+    printc('\tcase '+row[1]+': retval='+name.upper()+'; break; //'+row[2])
     i = i+1
 
-print("};\n", file=fh)
-print('''
-    }
-    return retval;
-}
-
-UA_VTable UA_ = {
+printh("};\n")
+printc('''\n}\nreturn retval;\n}\n
+const UA_VTable UA_ = {
 \t.getTypeIndex = UA_ns0ToVTableIndex,
-\t.types = (UA_VTable_Entry[]){''', file=fc)
+\t.types = (UA_VTable_Entry[]){''')
 
 for row in rows:
     if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
@@ -123,9 +132,9 @@ for row in rows:
     else:
 	name = "UA_" + row[0]
 
-    print('#define '+name.upper()+'_NS0 '+row[1], file=fh)
+    printh('#define '+name.upper()+'_NS0 '+row[1])
 
-    print("\t{.typeId={UA_NODEIDTYPE_FOURBYTE,0,.identifier.numeric=" + row[1] +"}"+ 
+    printc("\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"+
@@ -133,20 +142,20 @@ for row in rows:
           ",.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" +
+          ",.dynMembers=" + ("UA_FALSE" if (name in fixed_size) else "UA_TRUE") +
+          ",.encodings={{.calcSize=(UA_calcSize)"+ name +"_calcSizeBinary" +
           ",.encode=(UA_encode)"+name+ "_encodeBinary" +
           ",.decode=(UA_decode)"+name+"_decodeBinary}"+
-          ",(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeXml" +
+          ",{.calcSize=(UA_calcSize)"+ name +"_calcSizeXml" +
           ",.encode=(UA_encode)"+name+ "_encodeXml" +
           ",.decode=(UA_decode)"+name+"_decodeXml}"+
-          "}},",
-          end='\n',file=fc) 
+          "}},")
 
-print('''}};
+printc('''}};
 
-UA_VTable UA_noDelete_ = {
+const UA_VTable UA_noDelete_ = {
 \t.getTypeIndex=UA_ns0ToVTableIndex,
-\t.types = (UA_VTable_Entry[]){''', end='\n', file=fc)
+\t.types = (UA_VTable_Entry[]){''')
 
 for row in rows:
     if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
@@ -158,7 +167,7 @@ for row in rows:
     else:	
 	name = "UA_" + row[0]
 
-    print("\t{.typeId={UA_NODEIDTYPE_FOURBYTE,0,.identifier.numeric=" + row[1] +"}"+ 
+    printc("\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"+
@@ -166,19 +175,17 @@ for row in rows:
           ",.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" +
+          ",.dynMembers=" + ("UA_FALSE" if (name in fixed_size) else "UA_TRUE") +
+          ",.encodings={{.calcSize=(UA_calcSize)"+ name +"_calcSizeBinary" +
           ",.encode=(UA_encode)"+name+ "_encodeBinary" +
           ",.decode=(UA_decode)"+name+"_decodeBinary}"+
-          ",(UA_Encoding){.calcSize=(UA_calcSize)"+ name +"_calcSizeXml" +
+          ",{.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)
+printc("}};")
+printh('\n#endif /* OPCUA_NAMESPACE_0_H_ */')
 
 fh.close()
 fc.close()

+ 4 - 40
tools/indent.sh

@@ -3,49 +3,13 @@ if [ $# -eq 0 ]; then
 echo "usage: $0 <file1 file2 ...>"
    exit 1
 fi
-if [ "$(type -t indent)" = "" ]; then
-echo "Please install GNU indent first."
+if [ "$(type -t uncrustify)" = "" ]; then
+echo "Please install uncrustify first."
    exit 1
 fi
 
-# Assume a width of 4 spaces per tab.
-# E.g. when indenting to the opening braces of an argument list.
-
-indent \
---line-length120 \
---comment-line-length100 \
---indent-level4 \
---use-tabs \
---tab-size4 \
---case-indentation0 \
---declaration-indentation1 \
---ignore-newlines \
---swallow-optional-blank-lines \
---blank-lines-after-procedures \
---no-blank-lines-after-commas \
---break-after-boolean-operator \
---no-space-after-for \
---no-space-after-if \
---no-space-after-while \
---no-space-after-casts \
---braces-on-if-line \
---braces-on-func-def-line \
---braces-on-struct-decl-line \
---cuddle-do-while \
---cuddle-else \
---dont-break-procedure-type \
---continue-at-parentheses \
---no-space-after-function-call-names \
---no-space-after-parentheses \
---no-comment-delimiters-on-blank-lines \
---comment-indentation0 \
---format-first-column-comments \
---declaration-comment-column0 \
---format-all-comments \
---line-comments-indentation0 \
---space-special-semicolon \
-$@
-
+TOOL_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+uncrustify -c $TOOL_DIR/open62541.uncrustify.cfg -l C --replace $@
 
 # Remove trailing whitespace
 for file in $@; do