Leon Urbas 10 years ago
parent
commit
afc7b6c7a8
5 changed files with 122 additions and 91 deletions
  1. 59 62
      examples/src/generateSam.c
  2. 9 25
      examples/src/xml2ns0.c
  3. 40 0
      src/ua_xml.c
  4. 10 0
      src/ua_xml.h
  5. 4 4
      tests/check_namespace.c

+ 59 - 62
examples/src/generateSam.c

@@ -6,31 +6,45 @@
  */
  */
 
 
 #include "ua_xml.h"
 #include "ua_xml.h"
-#include <fcntl.h>
-#include <ctype.h>
+#include <ctype.h> // tolower
 
 
-/** @brief some macros to lowercase the first character without copying around */
-#define F_cls "%c%.*s"
-#define LC_cls(str) tolower((str).data[0]), (str).length-1, &((str).data[1])
+/** @brief we need a variable global to the module to make it possible for the visitors to access the namespace */
+static Namespace* theNamespace;
 
 
-/** @brief check if node is root node by scanning it's references for hasProperty
- */
-_Bool UA_Node_isRootNode(const UA_Node* node) {
+/** @brief check if VariableNode is root by searching for parent and checking if this is not a VariableNode */
+_Bool UA_VariableNode_isRoot(const UA_VariableNode* node) {
 	UA_Int32 i;
 	UA_Int32 i;
 	for (i = 0; i < node->referencesSize; i++ ) {
 	for (i = 0; i < node->referencesSize; i++ ) {
 		UA_Int32 refId = UA_NodeId_getIdentifier(&(node->references[i]->referenceTypeId));
 		UA_Int32 refId = UA_NodeId_getIdentifier(&(node->references[i]->referenceTypeId));
 		UA_Int32 isInverse = node->references[i]->isInverse;
 		UA_Int32 isInverse = node->references[i]->isInverse;
-		if (isInverse && (refId == 47 || refId == 46)) // HasComponent, HasProperty
-			return UA_FALSE;
+		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);
+			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);
+				}
+				Namespace_Entry_Lock_release(lock);
+				return UA_FALSE;
+			}
+			Namespace_Entry_Lock_release(lock);
+		}
 	}
 	}
 	return UA_TRUE;
 	return UA_TRUE;
 }
 }
 
 
+/** @brief some macros to lowercase the first character without copying around */
+#define F_cls "%c%.*s"
+#define LC_cls(str) tolower((str).data[0]), (str).length-1, &((str).data[1])
+
+
 /** @brief declares all the top level objects in the server's application memory
 /** @brief declares all the top level objects in the server's application memory
  * FIXME: shall add only top level objects, i.e. those that have no parents
  * FIXME: shall add only top level objects, i.e. those that have no parents
  */
  */
 void sam_declareAttribute(UA_Node const * node) {
 void sam_declareAttribute(UA_Node const * node) {
-	if ((node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_OBJECT) && UA_Node_isRootNode(node)) {
+	if (node->nodeClass == UA_NODECLASS_VARIABLE && UA_VariableNode_isRoot((UA_VariableNode*)node)) {
 		UA_VariableNode* vn = (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_[UA_ns0ToVTableIndex(vn->dataType.identifier.numeric)].name, LC_cls(node->browseName.name), node->nodeId.identifier.numeric);
 	}
 	}
@@ -85,26 +99,6 @@ void sam_attachToNamespace(UA_Node const * node) {
 	}
 	}
 }
 }
 
 
-typedef struct pattern {
-		char* s;
-		Namespace_nodeVisitor v;
-} pattern;
-
-pattern p[] = {
-{ "/** server application memory - generated but manually adapted */\n",UA_NULL },
-{ "#define SAM_ASSIGN_CSTRING(src,dst) do { dst.length = strlen(src)-1; dst.data = (UA_Byte*) src; } while(0)\n",UA_NULL },
-{ "struct sam {\n", UA_NULL },
-{ UA_NULL, sam_declareAttribute },
-{ "} sam;\n", UA_NULL },
-{ UA_NULL, sam_declareBuffer },
-{ "void sam_init(Namespace* ns) {", UA_NULL },
-{ UA_NULL, sam_assignBuffer },
-{ UA_NULL, sam_attachToNamespace },
-{ "}\n", UA_NULL },
-{UA_NULL, UA_NULL}
-};
-
-
 UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const * id, UA_Int32* number) {
 UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const * id, UA_Int32* number) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
 	UA_Node const * node;
@@ -177,42 +171,45 @@ UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_
 	return retval;
 	return retval;
 }
 }
 
 
+
+/** @ brief poor man's text template processor
+ * for p in patterns: print p.s, iterate over namespace with p.v */
+typedef struct pattern {
+		char* s;
+		Namespace_nodeVisitor v;
+} pattern;
+
+pattern p[] = {
+{ "/** server application memory - generated but manually adapted */\n",UA_NULL },
+{ "#define SAM_ASSIGN_CSTRING(src,dst) do { dst.length = strlen(src)-1; dst.data = (UA_Byte*) src; } while(0)\n",UA_NULL },
+{ "struct sam {\n", sam_declareAttribute },
+{ "} sam;\n", UA_NULL },
+{ UA_NULL, sam_declareBuffer },
+{ "void sam_init(Namespace* ns) {\n", sam_assignBuffer },
+{ UA_NULL, sam_attachToNamespace },
+{ "}\n", UA_NULL },
+{UA_NULL, UA_NULL} // terminal node : both elements UA_NULL
+};
+
 int main(int argc, char** argv) {
 int main(int argc, char** argv) {
 	if (argc != 2) {
 	if (argc != 2) {
 		printf("usage: %s filename\n",argv[0]);
 		printf("usage: %s filename\n",argv[0]);
 	} else {
 	} else {
-		int f = open(argv[1], O_RDONLY);
-		if (f==-1) {
-			perror("file not found");
-			exit(-1);
-		}
-
-		char buf[1024];
-		int len; /* len is the number of bytes in the current bufferful of data */
-		XML_Stack s;
-		XML_Stack_init(&s, "ROOT");
-		UA_NodeSet n;
-		UA_NodeSet_init(&n, 0);
-		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 = read(f, buf, 1024)) > 0) {
-			if (!XML_Parse(parser, buf, len, (len < 1024))) {
-				return 1;
-			}
-		}
-		XML_ParserFree(parser);
-		close(f);
-
-		for (pattern* pi = &p[0]; pi->s != UA_NULL || pi->v != UA_NULL; ++pi) {
-			if (pi->v) {
-				Namespace_iterate(n.ns, pi->v);
-			} else {
-				printf("%s\n",pi->s);
+		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;
 	return 0;

+ 9 - 25
examples/src/xml2ns0.c

@@ -172,32 +172,16 @@ UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_
 }
 }
 
 
 int main() {
 int main() {
-	char buf[1024];
-	int len; /* len is the number of bytes in the current bufferful of data */
-	XML_Stack s;
-	XML_Stack_init(&s, "ROOT");
-	UA_NodeSet n;
-	UA_NodeSet_init(&n, 0);
-	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 = read(0, buf, 1024)) > 0) {
-		if (!XML_Parse(parser, buf, len, (len < 1024))) {
-			return 1;
-		}
-	}
-	XML_ParserFree(parser);
+	Namespace* ns;
+	UA_Int32 retval;
 
 
-	DBG_VERBOSE(printf("aliases addr=%p, size=%d\n", (void*) &(n.aliases), n.aliases.size));
-	DBG_VERBOSE(UA_NodeSetAliases_println("aliases in nodeset: ", &n.aliases));
+	retval = Namespace_loadFromFile(&ns, 0, "ROOT", UA_NULL);
 
 
-	sam_init(n.ns);
-	// Namespace_iterate(n.ns, print_node);
+	sam_init(ns);
+	// Namespace_iterate(ns, print_node);
 
 
-	// Direct encoding
+	// encoding buffer
+	char buf[1024];
 	UA_ByteString buffer = { 1024, (UA_Byte*) buf };
 	UA_ByteString buffer = { 1024, (UA_Byte*) buf };
 	UA_Int32 pos = 0;
 	UA_Int32 pos = 0;
 
 
@@ -207,13 +191,13 @@ int main() {
 	nodeid.identifier.numeric = 2256; // ServerStatus
 	nodeid.identifier.numeric = 2256; // ServerStatus
 
 
 	UA_Int32 i=0;
 	UA_Int32 i=0;
-	UA_Int32 retval=UA_SUCCESS;
+	retval=UA_SUCCESS;
 	UA_DateTime tStart = UA_DateTime_now();
 	UA_DateTime tStart = UA_DateTime_now();
 	// encoding takes roundabout 10 µs on my virtual machine with -O0, so 1E5 takes a second
 	// encoding takes roundabout 10 µs on my virtual machine with -O0, so 1E5 takes a second
 	for (i=0;i<1E5 && retval == UA_SUCCESS;i++) {
 	for (i=0;i<1E5 && retval == UA_SUCCESS;i++) {
 		pos = 0;
 		pos = 0;
 		sam.serverStatus.currentTime = UA_DateTime_now();
 		sam.serverStatus.currentTime = UA_DateTime_now();
-		retval |= UAX_NodeId_encodeBinary(n.ns,&nodeid,&pos,&buffer);
+		retval |= UAX_NodeId_encodeBinary(ns,&nodeid,&pos,&buffer);
 	}
 	}
 	UA_DateTime tEnd = UA_DateTime_now();
 	UA_DateTime tEnd = UA_DateTime_now();
 	// tStart, tEnd count in 100 ns steps, so 10 steps = 1 µs
 	// tStart, tEnd count in 100 ns steps, so 10 steps = 1 µs

+ 40 - 0
src/ua_xml.c

@@ -6,6 +6,8 @@
  */
  */
 
 
 #include "ua_xml.h"
 #include "ua_xml.h"
+#include <fcntl.h> // open, O_RDONLY
+
 
 
 UA_Int32 UA_TypedArray_init(UA_TypedArray* p) {
 UA_Int32 UA_TypedArray_init(UA_TypedArray* p) {
 	p->size = -1;
 	p->size = -1;
@@ -991,3 +993,41 @@ void XML_Stack_endElement(void *data, const char *el) {
 	}
 	}
 	s->depth--;
 	s->depth--;
 }
 }
+
+UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char* rootName,const char* fileName) {
+	int f;
+	if (fileName == UA_NULL)
+		f = 0; // stdin
+	else if ((f= open(fileName, O_RDONLY)) == -1)
+		return UA_ERR_INVALID_VALUE;
+
+	char buf[1024];
+	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);
+	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 = read(f, buf, 1024)) > 0) {
+		if (!XML_Parse(parser, buf, len, (len < 1024))) {
+			return 1;
+		}
+	}
+	XML_ParserFree(parser);
+	close(f);
+
+	DBG_VERBOSE(printf("Namespace_loadFromFile - aliases addr=%p, size=%d\n", (void*) &(n.aliases), n.aliases.size));
+	DBG_VERBOSE(UA_NodeSetAliases_println("Namespace_loadFromFile - elements=", &n.aliases));
+
+	// eventually return the namespace object that has been allocated in UA_NodeSet_init
+	*ns = n.ns;
+	return UA_SUCCESS;
+}
+

+ 10 - 0
src/ua_xml.h

@@ -104,4 +104,14 @@ 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);
 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__
 #endif // __UA_XML_H__

+ 4 - 4
tests/check_namespace.c

@@ -211,8 +211,6 @@ Suite * namespace_suite (void) {
 	tcase_add_test (tc_cd, test_Namespace);
 	tcase_add_test (tc_cd, test_Namespace);
 	suite_add_tcase (s, tc_cd);
 	suite_add_tcase (s, tc_cd);
 
 
-
-
 	TCase* tc_find = tcase_create ("Find");
 	TCase* tc_find = tcase_create ("Find");
 	tcase_add_test (tc_find, findNodeInNamespaceWithSingleEntry);
 	tcase_add_test (tc_find, findNodeInNamespaceWithSingleEntry);
 	tcase_add_test (tc_find, findNodeInNamespaceWithTwoEntries);
 	tcase_add_test (tc_find, findNodeInNamespaceWithTwoEntries);
@@ -220,10 +218,12 @@ Suite * namespace_suite (void) {
 	tcase_add_test (tc_find, findNodeInExpandedNamespace);
 	tcase_add_test (tc_find, findNodeInExpandedNamespace);
 	tcase_add_test (tc_find, failToFindNonExistantNodeInNamespaceWithSeveralEntries);
 	tcase_add_test (tc_find, failToFindNonExistantNodeInNamespaceWithSeveralEntries);
 	tcase_add_test (tc_find, failToFindNodeInOtherNamespace);
 	tcase_add_test (tc_find, failToFindNodeInOtherNamespace);
-	tcase_add_test (tc_find, iterateOverNamespaceShallNotVisitEmptyNodes);
-	tcase_add_test (tc_find, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
 	suite_add_tcase (s, tc_find);
 	suite_add_tcase (s, tc_find);
 
 
+	TCase* tc_iterate = tcase_create ("Iterate");
+	tcase_add_test (tc_find, iterateOverNamespaceShallNotVisitEmptyNodes);
+	tcase_add_test (tc_find, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
+	suite_add_tcase (s, tc_iterate);
 
 
 	return s;
 	return s;
 }
 }