ua_xml.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /*
  2. * ua_xml.c
  3. *
  4. * Created on: 03.05.2014
  5. * Author: mrt
  6. */
  7. #include "ua_xml.h"
  8. #include <fcntl.h> // open, O_RDONLY
  9. UA_Int32 UA_TypedArray_init(UA_TypedArray* p) {
  10. p->size = -1;
  11. p->vt = &UA_[UA_INVALIDTYPE];
  12. p->elements = UA_NULL;
  13. return UA_SUCCESS;
  14. }
  15. UA_Int32 UA_TypedArray_new(UA_TypedArray** p) {
  16. UA_alloc((void** )p, sizeof(UA_TypedArray));
  17. UA_TypedArray_init(*p);
  18. return UA_SUCCESS;
  19. }
  20. UA_Int32 UA_TypedArray_setType(UA_TypedArray* p, UA_Int32 type) {
  21. UA_Int32 retval = UA_ERR_INVALID_VALUE;
  22. if (type >= UA_BOOLEAN && type <= UA_INVALIDTYPE) {
  23. p->vt = &UA_[type];
  24. retval = UA_SUCCESS;
  25. }
  26. return retval;
  27. }
  28. // FIXME: We might want to have these classes and their methods
  29. // defined in opcua.h via generate_builtin and the plugin-concept
  30. // or in ua_basictypes.c
  31. UA_Int32 UA_NodeSetAlias_init(UA_NodeSetAlias* p) {
  32. UA_String_init(&(p->alias));
  33. UA_String_init(&(p->value));
  34. return UA_SUCCESS;
  35. }
  36. UA_Int32 UA_NodeSetAlias_new(UA_NodeSetAlias** p) {
  37. UA_alloc((void** )p, sizeof(UA_NodeSetAlias));
  38. UA_NodeSetAlias_init(*p);
  39. return UA_SUCCESS;
  40. }
  41. UA_Int32 UA_NodeSetAliases_init(UA_NodeSetAliases* p) {
  42. p->size = -1;
  43. p->aliases = UA_NULL;
  44. return UA_SUCCESS;
  45. }
  46. UA_Int32 UA_NodeSetAliases_new(UA_NodeSetAliases** p) {
  47. UA_alloc((void** )p, sizeof(UA_NodeSetAliases));
  48. UA_NodeSetAliases_init(*p);
  49. return UA_SUCCESS;
  50. }
  51. UA_Int32 UA_NodeSetAliases_println(cstring label, UA_NodeSetAliases *p) {
  52. UA_Int32 i;
  53. for (i = 0; i < p->size; i++) {
  54. UA_NodeSetAlias* a = p->aliases[i];
  55. printf("%s{addr=%p", label, (void*) a);
  56. if (a) {
  57. printf(",alias='%.*s', value='%.*s'", a->alias.length, a->alias.data, a->value.length, a->value.data);
  58. }
  59. printf("}\n");
  60. }
  61. return UA_SUCCESS;
  62. }
  63. UA_Int32 UA_NodeSet_init(UA_NodeSet* p, UA_UInt32 nsid) {
  64. Namespace_new(&(p->ns), 100, nsid);
  65. p->aliases.size = -1;
  66. p->aliases.aliases = UA_NULL;
  67. return UA_SUCCESS;
  68. }
  69. UA_Int32 UA_NodeSet_new(UA_NodeSet** p, UA_UInt32 nsid) {
  70. UA_alloc((void** )p, sizeof(UA_NodeSet));
  71. UA_NodeSet_init(*p, nsid);
  72. return UA_SUCCESS;
  73. }
  74. UA_Int32 UA_NodeId_copycstring(cstring src, UA_NodeId* dst, UA_NodeSetAliases* aliases) {
  75. dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
  76. dst->namespace = 0;
  77. dst->identifier.numeric = 0;
  78. // FIXME: assumes i=nnnn
  79. if (src[1] == '=') {
  80. dst->identifier.numeric = atoi(&src[2]);
  81. } else {
  82. UA_Int32 i;
  83. for (i = 0; i < aliases->size && dst->identifier.numeric == 0; ++i) {
  84. if (0
  85. == strncmp((char const*) src, (char const*) aliases->aliases[i]->alias.data,
  86. aliases->aliases[i]->alias.length)) {
  87. dst->identifier.numeric = atoi((char const*) &(aliases->aliases[i]->value.data[2]));
  88. }
  89. }
  90. }
  91. DBG_VERBOSE(printf("UA_NodeId_copycstring src=%s,id=%d\n", src, dst->identifier.numeric));
  92. return UA_SUCCESS;
  93. }
  94. UA_Int32 UA_ReferenceNode_println(cstring label, UA_ReferenceNode *a) {
  95. printf("%s{referenceType=%d, target=%d, isInverse=%d}\n",
  96. label,
  97. a->referenceTypeId.identifier.numeric,
  98. a->targetId.nodeId.identifier.numeric,
  99. a->isInverse);
  100. return UA_SUCCESS;
  101. }
  102. UA_Int32 UA_ExpandedNodeId_copycstring(cstring src, UA_ExpandedNodeId* dst, UA_NodeSetAliases* aliases) {
  103. dst->nodeId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
  104. dst->nodeId.namespace = 0;
  105. dst->nodeId.identifier.numeric = 0;
  106. UA_NodeId_copycstring(src, &(dst->nodeId), aliases);
  107. DBG_VERBOSE(printf("UA_ExpandedNodeId_copycstring src=%s,id=%d\n", src, dst->nodeId.identifier.numeric));
  108. return UA_SUCCESS;
  109. }
  110. void XML_Stack_init(XML_Stack* p, cstring name) {
  111. unsigned int i, j;
  112. p->depth = 0;
  113. for (i = 0; i < XML_STACK_MAX_DEPTH; i++) {
  114. p->parent[i].name = UA_NULL;
  115. p->parent[i].len = 0;
  116. p->parent[i].activeChild = -1;
  117. p->parent[i].textAttrib = UA_NULL;
  118. p->parent[i].textAttribIdx = -1;
  119. for (j = 0; j < XML_STACK_MAX_CHILDREN; j++) {
  120. p->parent[i].children[j].name = UA_NULL;
  121. p->parent[i].children[j].length = -1;
  122. p->parent[i].children[j].elementHandler = UA_NULL;
  123. p->parent[i].children[j].type = UA_INVALIDTYPE;
  124. p->parent[i].children[j].obj = UA_NULL;
  125. }
  126. }
  127. p->parent[0].name = name;
  128. }
  129. char path_buffer[1024];
  130. char * XML_Stack_path(XML_Stack* s) {
  131. UA_Int32 i;
  132. char *p = &path_buffer[0];
  133. for (i = 0; i <= s->depth; i++) {
  134. strcpy(p, s->parent[i].name);
  135. p += strlen(s->parent[i].name);
  136. *p = '/';
  137. p++;
  138. }
  139. *p=0;
  140. return &path_buffer[0];
  141. }
  142. void XML_Stack_print(XML_Stack* s) {
  143. printf("%s", XML_Stack_path(s));
  144. }
  145. // FIXME: we might want to calculate textAttribIdx from a string and the information given on the stack
  146. void XML_Stack_handleTextAsElementOf(XML_Stack* p, cstring textAttrib, unsigned int textAttribIdx) {
  147. p->parent[p->depth].textAttrib = textAttrib;
  148. p->parent[p->depth].textAttribIdx = textAttribIdx;
  149. }
  150. void XML_Stack_addChildHandler(XML_Stack* p, cstring name, UA_Int32 length, XML_decoder handler, UA_Int32 type, void* dst) {
  151. unsigned int len = p->parent[p->depth].len;
  152. p->parent[p->depth].children[len].name = name;
  153. p->parent[p->depth].children[len].length = length;
  154. p->parent[p->depth].children[len].elementHandler = handler;
  155. p->parent[p->depth].children[len].type = type;
  156. p->parent[p->depth].children[len].obj = dst;
  157. p->parent[p->depth].len++;
  158. }
  159. UA_Int32 UA_Int16_copycstring(cstring src, UA_Int16* dst) {
  160. *dst = atoi(src);
  161. return UA_SUCCESS;
  162. }
  163. UA_Int32 UA_UInt16_copycstring(cstring src, UA_UInt16* dst) {
  164. *dst = atoi(src);
  165. return UA_SUCCESS;
  166. }
  167. UA_Int32 UA_Int16_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int16* dst, _Bool isStart) {
  168. DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  169. if (isStart) {
  170. if (dst == UA_NULL) {
  171. UA_Int16_new(&dst);
  172. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  173. }
  174. UA_Int16_copycstring((cstring) attr[1], dst);
  175. }
  176. return UA_SUCCESS;
  177. }
  178. UA_Int32 UA_Int32_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Int32* dst, _Bool isStart) {
  179. DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  180. if (isStart) {
  181. if (dst == UA_NULL) {
  182. UA_Int32_new(&dst);
  183. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  184. }
  185. *dst = atoi(attr[1]);
  186. }
  187. return UA_SUCCESS;
  188. }
  189. UA_Int32 UA_Text_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Byte** dst, _Bool isStart) {
  190. DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  191. UA_UInt32 i;
  192. if (isStart) {
  193. if (dst == UA_NULL) {
  194. UA_alloc((void**)&dst,sizeof(void*));
  195. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  196. }
  197. // set attributes
  198. for (i = 0; attr[i]; i += 2) {
  199. if (0 == strncmp("Data", attr[i], strlen("Data"))) {
  200. char* tmp;
  201. UA_alloc((void**)&tmp,strlen(attr[i+1])+1);
  202. strncpy(tmp,attr[i+1],strlen(attr[i+1]));
  203. tmp[strlen(attr[i+1])] = 0;
  204. *dst = (UA_Byte*) tmp;
  205. } else {
  206. printf("UA_Text_decodeXML - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
  207. }
  208. }
  209. }
  210. return UA_SUCCESS;
  211. }
  212. UA_Int32 UA_String_decodeXML(XML_Stack* s, XML_Attr* attr, UA_String* dst, _Bool isStart) {
  213. DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  214. UA_UInt32 i;
  215. if (isStart) {
  216. if (dst == UA_NULL) {
  217. UA_String_new(&dst);
  218. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  219. }
  220. s->parent[s->depth].len = 0;
  221. XML_Stack_addChildHandler(s, "Data", strlen("Data"), (XML_decoder) UA_Text_decodeXML, UA_BYTE, &(dst->data));
  222. XML_Stack_addChildHandler(s, "Length", strlen("Length"), (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->length));
  223. XML_Stack_handleTextAsElementOf(s, "Data", 0);
  224. // set attributes
  225. for (i = 0; attr[i]; i += 2) {
  226. if (0 == strncmp("Data", attr[i], strlen("Data"))) {
  227. UA_String_copycstring(attr[i + 1], dst);
  228. } else {
  229. printf("UA_String_decodeXML - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
  230. }
  231. }
  232. } else {
  233. switch (s->parent[s->depth - 1].activeChild) {
  234. case 0:
  235. if (dst != UA_NULL && dst->data != UA_NULL && dst->length == -1) {
  236. dst->length = strlen((char const*)dst->data);
  237. }
  238. break;
  239. }
  240. }
  241. return UA_SUCCESS;
  242. }
  243. UA_Int32 UA_NodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeId* dst, _Bool isStart) {
  244. DBG_VERBOSE(printf("UA_NodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  245. UA_UInt32 i;
  246. if (isStart) {
  247. if (dst == UA_NULL) {
  248. UA_NodeId_new(&dst);
  249. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  250. }
  251. s->parent[s->depth].len = 0;
  252. XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"), (XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->namespace));
  253. XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"), (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->identifier.numeric));
  254. XML_Stack_addChildHandler(s, "Identifier", strlen("Identifier"), (XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
  255. XML_Stack_handleTextAsElementOf(s, "Data", 2);
  256. // set attributes
  257. for (i = 0; attr[i]; i += 2) {
  258. if (0 == strncmp("Namespace", attr[i], strlen("Namespace"))) {
  259. dst->namespace = atoi(attr[i + 1]);
  260. } else if (0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
  261. dst->identifier.numeric = atoi(attr[i + 1]);
  262. dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
  263. } else {
  264. printf("UA_NodeId_decodeXML - Unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
  265. }
  266. }
  267. } else {
  268. if (s->parent[s->depth - 1].activeChild == 2) {
  269. UA_NodeId_copycstring((cstring)((UA_String*)attr)->data,dst,s->aliases);
  270. }
  271. }
  272. return UA_SUCCESS;
  273. }
  274. UA_Int32 UA_ExpandedNodeId_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExpandedNodeId* dst, _Bool isStart) {
  275. DBG_VERBOSE(printf("UA_ExpandedNodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  276. UA_UInt32 i;
  277. if (isStart) {
  278. if (dst == UA_NULL) {
  279. UA_ExpandedNodeId_new(&dst);
  280. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  281. }
  282. s->parent[s->depth].len = 0;
  283. XML_Stack_addChildHandler(s, "NodeId", strlen("NodeId"), (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->nodeId));
  284. XML_Stack_addChildHandler(s, "Namespace", strlen("Namespace"),(XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->nodeId.namespace));
  285. XML_Stack_addChildHandler(s, "Numeric", strlen("Numeric"),(XML_decoder) UA_Int32_decodeXML, UA_INT32,
  286. &(dst->nodeId.identifier.numeric));
  287. XML_Stack_addChildHandler(s, "Id", strlen("Id"),(XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
  288. XML_Stack_handleTextAsElementOf(s, "Data", 3);
  289. // set attributes
  290. for (i = 0; attr[i]; i += 2) {
  291. if (0 == strncmp("Namespace", attr[i], strlen("Namespace"))) {
  292. UA_UInt16_copycstring((cstring) attr[i + 1], &(dst->nodeId.namespace));
  293. } else if (0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
  294. UA_NodeId_copycstring((cstring) attr[i + 1], &(dst->nodeId), s->aliases);
  295. } else if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
  296. UA_NodeId_copycstring((cstring) attr[i + 1], &(dst->nodeId), s->aliases);
  297. } else {
  298. printf("UA_ExpandedNodeId_decodeXML - unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
  299. }
  300. }
  301. }
  302. return UA_SUCCESS;
  303. }
  304. UA_Int32 UA_LocalizedText_decodeXML(XML_Stack* s, XML_Attr* attr, UA_LocalizedText* dst, _Bool isStart) {
  305. DBG_VERBOSE(printf("UA_LocalizedText entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  306. UA_UInt32 i;
  307. if (isStart) {
  308. if (dst == UA_NULL) {
  309. UA_LocalizedText_new(&dst);
  310. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  311. }
  312. // s->parent[s->depth].len = 0;
  313. XML_Stack_addChildHandler(s, "Text", strlen("Text"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->text));
  314. XML_Stack_addChildHandler(s, "Locale", strlen("Locale"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->locale));
  315. XML_Stack_handleTextAsElementOf(s, "Data", 0);
  316. // set attributes
  317. for (i = 0; attr[i]; i += 2) {
  318. if (0 == strncmp("Text", attr[i], strlen("Text"))) {
  319. UA_String_copycstring(attr[i + 1], &(dst->text));
  320. dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  321. } else if (0 == strncmp("Locale", attr[i], strlen("Locale"))) {
  322. UA_String_copycstring(attr[i + 1], &(dst->locale));
  323. dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  324. } else {
  325. perror("Unknown attribute");
  326. }
  327. }
  328. } else {
  329. switch (s->parent[s->depth - 1].activeChild) {
  330. case 0:
  331. dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  332. break;
  333. case 1:
  334. dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  335. break;
  336. default:
  337. break;
  338. }
  339. }
  340. return UA_SUCCESS;
  341. }
  342. UA_Int32 UA_QualifiedName_decodeXML(XML_Stack* s, XML_Attr* attr, UA_QualifiedName* dst, _Bool isStart) {
  343. DBG_VERBOSE(printf("UA_QualifiedName entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  344. UA_UInt32 i;
  345. if (isStart) {
  346. if (dst == UA_NULL) {
  347. UA_QualifiedName_new(&dst);
  348. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  349. }
  350. s->parent[s->depth].len = 0;
  351. XML_Stack_addChildHandler(s, "Name", strlen("Name"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->name));
  352. XML_Stack_addChildHandler(s, "NamespaceIndex", strlen("NamespaceIndex"), (XML_decoder) UA_Int16_decodeXML, UA_STRING,
  353. &(dst->namespaceIndex));
  354. XML_Stack_handleTextAsElementOf(s, "Data", 0);
  355. // set attributes
  356. for (i = 0; attr[i]; i += 2) {
  357. if (0 == strncmp("NamespaceIndex", attr[i], strlen("NamespaceIndex"))) {
  358. dst->namespaceIndex = atoi(attr[i + 1]);
  359. } else if (0 == strncmp("Name", attr[i], strlen("Name"))) {
  360. UA_String_copycstring(attr[i + 1], &(dst->name));
  361. } else {
  362. perror("Unknown attribute");
  363. }
  364. }
  365. }
  366. return UA_SUCCESS;
  367. }
  368. UA_Int32 UA_ReferenceNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ReferenceNode* dst, _Bool isStart) {
  369. DBG_VERBOSE(printf("UA_ReferenceNode_decodeXML entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  370. if (isStart) {
  371. // create if necessary
  372. if (dst == UA_NULL) {
  373. UA_ReferenceNode_new(&dst);
  374. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  375. }
  376. // set handlers
  377. s->parent[s->depth].len = 0;
  378. XML_Stack_addChildHandler(s, "ReferenceType", strlen("ReferenceType"),(XML_decoder) UA_NodeId_decodeXML, UA_STRING,
  379. &(dst->referenceTypeId));
  380. XML_Stack_addChildHandler(s, "IsForward", strlen("IsForward"), (XML_decoder) UA_Boolean_decodeXML, UA_STRING, &(dst->isInverse));
  381. XML_Stack_addChildHandler(s, "Target", strlen("Target"), (XML_decoder) UA_ExpandedNodeId_decodeXML, UA_STRING, &(dst->targetId));
  382. XML_Stack_handleTextAsElementOf(s, "NodeId", 2);
  383. // set attributes
  384. UA_Int32 i;
  385. for (i = 0; attr[i]; i += 2) {
  386. if (0 == strncmp("ReferenceType", attr[i], strlen("ReferenceType"))) {
  387. UA_NodeId_copycstring(attr[i + 1], &(dst->referenceTypeId), s->aliases);
  388. } else if (0 == strncmp("IsForward", attr[i], strlen("IsForward"))) {
  389. UA_Boolean_copycstring(attr[i + 1], &(dst->isInverse));
  390. dst->isInverse = !dst->isInverse;
  391. } else if (0 == strncmp("Target", attr[i], strlen("Target"))) {
  392. UA_ExpandedNodeId_copycstring(attr[i + 1], &(dst->targetId), s->aliases);
  393. } else {
  394. DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  395. }
  396. }
  397. }
  398. return UA_SUCCESS;
  399. }
  400. UA_Int32 UA_TypedArray_decodeXML(XML_Stack* s, XML_Attr* attr, UA_TypedArray* dst, _Bool isStart) {
  401. UA_Int32 type = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].type;
  402. cstring names = s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].name;
  403. DBG_VERBOSE(printf("UA_TypedArray_decodeXML - entered with dst=%p,isStart=%d,type={%d,%s},name=%s\n", (void* ) dst, isStart,type,UA_[type].name, names));
  404. if (isStart) {
  405. if (dst == UA_NULL) {
  406. UA_TypedArray_new(&dst);
  407. UA_TypedArray_setType(dst, type);
  408. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = dst;
  409. }
  410. // need to map from ArrayName to member name
  411. // References - Reference
  412. // Aliases - Alias
  413. // ListOfXX - XX
  414. UA_Int32 length = 0;
  415. if (0 == strncmp("ListOf",names,strlen("ListOf"))) {
  416. names = &names[strlen("ListOf")];
  417. length = strlen(names);
  418. } else if ( 0 == strncmp("References",names,strlen("References"))){
  419. length = strlen(names) - 1;
  420. } else if ( 0 == strncmp("Aliases",names,strlen("Aliases"))){
  421. length = strlen(names) - 2;
  422. }
  423. DBG(printf("UA_TypedArray_decodeXML - add handler for {%.*s}\n", length, names));
  424. XML_Stack_addChildHandler(s, names, length, (XML_decoder) UA_[type].decodeXML, type, UA_NULL);
  425. } else {
  426. // sub element is ready, add to array
  427. if (dst->size < 0 || dst->size == 0) {
  428. dst->size = 1;
  429. UA_alloc((void** )&(dst->elements), dst->size * sizeof(void*));
  430. DBG(printf("UA_TypedArray_decodeXML - allocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->elements),dst->size));
  431. } else {
  432. dst->size++;
  433. dst->elements = realloc(dst->elements, dst->size * sizeof(void*));
  434. DBG(printf("UA_TypedArray_decodeXML - reallocate elements:dst=%p, aliases=%p, size=%d\n", (void* )dst,(void* )(dst->elements), dst->size));
  435. }
  436. // index starts with 0, therefore size-1
  437. DBG_VERBOSE(printf("UA_TypedArray_decodeXML - assign element[%d], src=%p\n", dst->size - 1, (void* )attr));
  438. dst->elements[dst->size - 1] = (void*) attr;
  439. DBG_VERBOSE(printf("UA_TypedArray_decodeXML - clear %p\n",(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
  440. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  441. }
  442. return UA_SUCCESS;
  443. }
  444. UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_DataTypeNode* dst, _Bool isStart) {
  445. DBG_VERBOSE(printf("UA_DataTypeNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  446. UA_UInt32 i;
  447. if (isStart) {
  448. // create a new object if called with UA_NULL
  449. if (dst == UA_NULL) {
  450. UA_DataTypeNode_new(&dst);
  451. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  452. }
  453. s->parent[s->depth].len = 0;
  454. XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
  455. XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
  456. XML_Stack_addChildHandler(s, "BrowseName", strlen("BrowseName"),(XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME, &(dst->description));
  457. XML_Stack_addChildHandler(s, "IsAbstract", strlen("IsAbstract"),(XML_decoder) UA_Boolean_decodeXML, UA_BOOLEAN, &(dst->description));
  458. XML_Stack_addChildHandler(s, "References", strlen("References"),(XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE, UA_NULL);
  459. // set missing default attributes
  460. dst->nodeClass = UA_NODECLASS_DATATYPE;
  461. // set attributes
  462. for (i = 0; attr[i]; i += 2) {
  463. if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
  464. UA_NodeId_copycstring(attr[i + 1], &(dst->nodeId), s->aliases);
  465. } else if (0 == strncmp("BrowseName", attr[i], strlen("BrowseName"))) {
  466. UA_String_copycstring(attr[i + 1], &(dst->browseName.name));
  467. dst->browseName.namespaceIndex = 0;
  468. } else if (0 == strncmp("DisplayName", attr[i], strlen("DisplayName"))) {
  469. UA_String_copycstring(attr[i + 1], &(dst->displayName.text));
  470. dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  471. } else if (0 == strncmp("IsAbstract", attr[i], strlen("IsAbstract"))) {
  472. UA_Boolean_copycstring(attr[i + 1], &(dst->isAbstract));
  473. dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  474. } else if (0 == strncmp("Description", attr[i], strlen("Description"))) {
  475. UA_String_copycstring(attr[i + 1], &(dst->description.text));
  476. dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  477. } else {
  478. DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  479. }
  480. }
  481. } else {
  482. switch (s->parent[s->depth - 1].activeChild) {
  483. case 4: // References
  484. if (attr != UA_NULL) {
  485. UA_TypedArray* array = (UA_TypedArray *) attr;
  486. DBG_VERBOSE(printf("finished aliases: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
  487. dst->referencesSize = array->size;
  488. dst->references = (UA_ReferenceNode**) array->elements;
  489. }
  490. break;
  491. }
  492. }
  493. return UA_SUCCESS;
  494. }
  495. UA_Int32 UA_ObjectNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ObjectNode* dst, _Bool isStart) {
  496. DBG_VERBOSE(printf("UA_ObjectNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  497. UA_UInt32 i;
  498. if (isStart) {
  499. // create a new object if called with UA_NULL
  500. if (dst == UA_NULL) {
  501. UA_ObjectNode_new(&dst);
  502. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  503. }
  504. // s->parent[s->depth].len = 0;
  505. XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
  506. XML_Stack_addChildHandler(s, "Description", strlen("Description"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
  507. // FIXME: no idea how to handle SymbolicName automatically. Seems to me that it is the "real" BrowseName
  508. // XML_Stack_addChildHandler(s, "BrowseName", (XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME,&(dst->browseName));
  509. XML_Stack_addChildHandler(s, "SymbolicName", strlen("SymbolicName"), (XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME,&(dst->browseName));
  510. XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE, UA_NULL);
  511. // set missing default attributes
  512. dst->nodeClass = UA_NODECLASS_DATATYPE;
  513. // set attributes
  514. for (i = 0; attr[i]; i += 2) {
  515. if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
  516. UA_NodeId_copycstring(attr[i + 1], &(dst->nodeId), s->aliases);
  517. } else if (0 == strncmp("SymbolicName", attr[i], strlen("SymboliName"))) {
  518. UA_String_copycstring(attr[i + 1], &(dst->browseName.name));
  519. dst->browseName.namespaceIndex = 0;
  520. } else if (0 == strncmp("DisplayName", attr[i], strlen("DisplayName"))) {
  521. UA_String_copycstring(attr[i + 1], &(dst->displayName.text));
  522. dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  523. } else if (0 == strncmp("Description", attr[i], strlen("Description"))) {
  524. UA_String_copycstring(attr[i + 1], &(dst->description.text));
  525. dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  526. } else {
  527. DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  528. }
  529. }
  530. } else {
  531. if (s->parent[s->depth - 1].activeChild == 3 && attr != UA_NULL ) { // References Array
  532. UA_TypedArray* array = (UA_TypedArray*) attr;
  533. DBG(printf("UA_ObjectNode_decodeXML finished references: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
  534. dst->referencesSize = array->size;
  535. dst->references = (UA_ReferenceNode**) array->elements;
  536. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  537. }
  538. }
  539. return UA_SUCCESS;
  540. }
  541. UA_Int32 UA_Variant_decodeXML(XML_Stack* s, XML_Attr* attr, UA_Variant* dst, _Bool isStart) {
  542. DBG_VERBOSE(printf("UA_Variant entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  543. UA_UInt32 i;
  544. if (isStart) {
  545. // create a new object if called with UA_NULL
  546. if (dst == UA_NULL) {
  547. UA_Variant_new(&dst);
  548. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  549. }
  550. s->parent[s->depth].len = 0;
  551. XML_Stack_addChildHandler(s, "ListOfExtensionObject", strlen("ListOfExtensionObject"), (XML_decoder) UA_TypedArray_decodeXML, UA_EXTENSIONOBJECT, UA_NULL);
  552. XML_Stack_addChildHandler(s, "ListOfLocalizedText", strlen("ListOfLocalizedText"), (XML_decoder) UA_TypedArray_decodeXML, UA_LOCALIZEDTEXT, UA_NULL);
  553. // set attributes
  554. for (i = 0; attr[i]; i += 2) {
  555. {
  556. DBG_ERR(XML_Stack_print(s));
  557. DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  558. }
  559. }
  560. } else {
  561. if (s->parent[s->depth - 1].activeChild == 0 && attr != UA_NULL ) { // ExtensionObject
  562. UA_TypedArray* array = (UA_TypedArray*) attr;
  563. DBG_VERBOSE(printf("UA_Variant_decodeXML - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
  564. dst->arrayLength = array->size;
  565. dst->data = array->elements;
  566. dst->vt = &UA_[UA_EXTENSIONOBJECT];
  567. dst->encodingMask = UA_EXTENSIONOBJECT_NS0 & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  568. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  569. } else if (s->parent[s->depth - 1].activeChild == 1 && attr != UA_NULL ) { // LocalizedText
  570. UA_TypedArray* array = (UA_TypedArray*) attr;
  571. DBG_VERBOSE(printf("UA_Variant_decodeXML - finished array: references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
  572. dst->arrayLength = array->size;
  573. dst->data = array->elements;
  574. dst->vt = &UA_[UA_LOCALIZEDTEXT];
  575. dst->encodingMask = UA_LOCALIZEDTEXT_NS0 & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  576. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  577. }
  578. }
  579. return UA_SUCCESS;
  580. }
  581. UA_Int32 UA_ExtensionObject_decodeXML(XML_Stack* s, XML_Attr* attr, UA_ExtensionObject* dst, _Bool isStart) {
  582. DBG_VERBOSE(printf("UA_ExtensionObject entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  583. UA_UInt32 i;
  584. if (isStart) {
  585. // create a new object if called with UA_NULL
  586. if (dst == UA_NULL) {
  587. UA_ExtensionObject_new(&dst);
  588. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  589. }
  590. s->parent[s->depth].len = 0;
  591. XML_Stack_addChildHandler(s, "TypeId", strlen("TypeId"), (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->typeId));
  592. // XML_Stack_addChildHandler(s, "Body", strlen("Body"), (XML_decoder) UA_Body_decodeXML, UA_LOCALIZEDTEXT, UA_NULL);
  593. // set attributes
  594. for (i = 0; attr[i]; i += 2) {
  595. {
  596. DBG_ERR(XML_Stack_print(s));
  597. DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  598. }
  599. }
  600. }
  601. return UA_SUCCESS;
  602. }
  603. _Bool UA_NodeId_isBuiltinType(UA_NodeId* nodeid) {
  604. return (nodeid->namespace == 0 &&
  605. nodeid->identifier.numeric >= UA_BOOLEAN_NS0 &&
  606. nodeid->identifier.numeric <= UA_DIAGNOSTICINFO_NS0
  607. );
  608. }
  609. UA_Int32 UA_VariableNode_decodeXML(XML_Stack* s, XML_Attr* attr, UA_VariableNode* dst, _Bool isStart) {
  610. DBG_VERBOSE(printf("UA_VariableNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  611. UA_UInt32 i;
  612. if (isStart) {
  613. // create a new object if called with UA_NULL
  614. if (dst == UA_NULL) {
  615. UA_VariableNode_new(&dst);
  616. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  617. }
  618. s->parent[s->depth].len = 0;
  619. XML_Stack_addChildHandler(s, "DisplayName", strlen("DisplayName"), (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
  620. &(dst->displayName));
  621. XML_Stack_addChildHandler(s, "Description", strlen("Description"),(XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
  622. &(dst->description));
  623. XML_Stack_addChildHandler(s, "DataType", strlen("DataType"),(XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->dataType));
  624. XML_Stack_addChildHandler(s, "ValueRank", strlen("ValueRank"),(XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->valueRank));
  625. XML_Stack_addChildHandler(s, "Value", strlen("Value"),(XML_decoder) UA_Variant_decodeXML, UA_VARIANT, &(dst->value));
  626. XML_Stack_addChildHandler(s, "References", strlen("References"), (XML_decoder) UA_TypedArray_decodeXML, UA_REFERENCENODE,
  627. UA_NULL);
  628. // set missing default attributes
  629. dst->nodeClass = UA_NODECLASS_VARIABLE;
  630. // set attributes
  631. for (i = 0; attr[i]; i += 2) {
  632. if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
  633. UA_NodeId_copycstring(attr[i + 1], &(dst->nodeId), s->aliases);
  634. } else if (0 == strncmp("DataType", attr[i], strlen("DataType"))) {
  635. UA_NodeId_copycstring(attr[i + 1], &(dst->dataType), s->aliases);
  636. if (UA_NodeId_isBuiltinType(&(dst->dataType))) {
  637. dst->value.encodingMask = dst->dataType.identifier.numeric;
  638. dst->value.vt = &UA_[UA_ns0ToVTableIndex(dst->dataType.identifier.numeric)];
  639. } else {
  640. dst->value.encodingMask = UA_EXTENSIONOBJECT_NS0;
  641. dst->value.vt = &UA_[UA_EXTENSIONOBJECT];
  642. }
  643. } else if (0 == strncmp("ValueRank", attr[i], strlen("ValueRank"))) {
  644. dst->valueRank = atoi(attr[i + 1]);
  645. } else if (0 == strncmp("ParentNodeId", attr[i], strlen("ParentNodeId"))) {
  646. // FIXME: this seems to be redundant to the hasProperty-reference
  647. } else if (0 == strncmp("BrowseName", attr[i], strlen("BrowseName"))) {
  648. UA_String_copycstring(attr[i + 1], &(dst->browseName.name));
  649. dst->browseName.namespaceIndex = 0;
  650. } else if (0 == strncmp("DisplayName", attr[i], strlen("DisplayName"))) {
  651. UA_String_copycstring(attr[i + 1], &(dst->displayName.text));
  652. dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  653. } else if (0 == strncmp("Description", attr[i], strlen("Description"))) {
  654. UA_String_copycstring(attr[i + 1], &(dst->description.text));
  655. dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  656. } else {
  657. DBG_ERR(XML_Stack_print(s));
  658. DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  659. }
  660. }
  661. } else {
  662. if (s->parent[s->depth - 1].activeChild == 5 && attr != UA_NULL) { // References
  663. UA_TypedArray* array = (UA_TypedArray*) attr;
  664. DBG(printf("UA_VariableNode_decodeXML - finished references=%p, size=%d\n",(void*)array,(array==UA_NULL)?-1:array->size));
  665. dst->referencesSize = array->size;
  666. dst->references = (UA_ReferenceNode**) array->elements;
  667. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  668. }
  669. }
  670. return UA_SUCCESS;
  671. }
  672. void print_node(UA_Node const * node) {
  673. if (node != UA_NULL) {
  674. UA_NodeId_printf("node.nodeId=", &(node->nodeId));
  675. printf("\t.browseName='%.*s'\n", node->browseName.name.length, node->browseName.name.data);
  676. printf("\t.displayName='%.*s'\n", node->displayName.text.length, node->displayName.text.data);
  677. printf("\t.description='%.*s%s'\n", node->description.text.length > 40 ? 40 : node->description.text.length,
  678. node->description.text.data, node->description.text.length > 40 ? "..." : "");
  679. printf("\t.nodeClass=%d\n", node->nodeClass);
  680. printf("\t.writeMask=%d\n", node->writeMask);
  681. printf("\t.userWriteMask=%d\n", node->userWriteMask);
  682. printf("\t.references.size=%d\n", node->referencesSize);
  683. UA_Int32 i;
  684. for (i=0;i<node->referencesSize;i++) {
  685. printf("\t\t.element[%d]", i);
  686. UA_ReferenceNode_println("=",node->references[i]);
  687. }
  688. switch (node->nodeClass) {
  689. case UA_NODECLASS_VARIABLE: {
  690. UA_VariableNode const * p = (UA_VariableNode const *) node;
  691. printf("\t----- UA_VariableNode ----- \n");
  692. UA_NodeId_printf("\t.dataType=", &(p->dataType));
  693. printf("\t.valueRank=%d\n", p->valueRank);
  694. printf("\t.accessLevel=%d\n", p->accessLevel);
  695. printf("\t.userAccessLevel=%d\n", p->userAccessLevel);
  696. printf("\t.arrayDimensionsSize=%d\n", p->arrayDimensionsSize);
  697. printf("\t.minimumSamplingInterval=%f\n", p->minimumSamplingInterval);
  698. printf("\t.historizing=%d\n", p->historizing);
  699. printf("\t----- UA_Variant ----- \n");
  700. printf("\t.value.type.name=%s\n", p->value.vt->name);
  701. printf("\t.value.array.length=%d\n", p->value.arrayLength);
  702. UA_Int32 i;
  703. for (i=0;i<p->value.arrayLength || (p->value.arrayLength==-1 && i==0);++i) {
  704. printf("\t.value.array.element[%d]=%p", i, (p->value.data == UA_NULL ? UA_NULL : p->value.data[i]));
  705. switch (p->value.vt->ns0Id) {
  706. case UA_LOCALIZEDTEXT_NS0: {
  707. if (p->value.data != UA_NULL) {
  708. UA_LocalizedText* ltp = (UA_LocalizedText*) p->value.data[i];
  709. printf(",enc=%d,locale={%d,{%.*s}},text={%d,{%.*s}}",ltp->encodingMask,ltp->locale.length,ltp->locale.length,ltp->locale.data,ltp->text.length,ltp->text.length,ltp->text.data);
  710. }
  711. }
  712. break;
  713. case UA_EXTENSIONOBJECT_NS0: {
  714. if (p->value.data != UA_NULL) {
  715. UA_ExtensionObject* eo = (UA_ExtensionObject*) p->value.data[i];
  716. if (eo == UA_NULL) {
  717. printf(",(null)");
  718. } else {
  719. printf(",enc=%d,typeId={i=%d}",eo->encoding,eo->typeId.identifier.numeric);
  720. }
  721. }
  722. }
  723. break;
  724. default:
  725. break;
  726. }
  727. printf("\n");
  728. }
  729. }
  730. break;
  731. // case UA_NODECLASS_DATATYPE:
  732. default:
  733. break;
  734. }
  735. }
  736. }
  737. UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAlias* dst, _Bool isStart) {
  738. DBG_VERBOSE(printf("UA_NodeSetAlias entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  739. if (isStart) {
  740. // create if necessary
  741. if (dst == UA_NULL) {
  742. UA_NodeSetAlias_new(&dst);
  743. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  744. }
  745. // set handlers
  746. s->parent[s->depth].len = 0;
  747. XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->alias));
  748. XML_Stack_addChildHandler(s, "Value", strlen("Value"), (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->value));
  749. XML_Stack_handleTextAsElementOf(s, "Data", 1);
  750. // set attributes
  751. UA_Int32 i;
  752. for (i = 0; attr[i]; i += 2) {
  753. if (0 == strncmp("Alias", attr[i], strlen("Alias"))) {
  754. UA_String_copycstring(attr[i + 1], &(dst->alias));
  755. } else if (0 == strncmp("Value", attr[i], strlen("Value"))) {
  756. UA_String_copycstring(attr[i + 1], &(dst->value));
  757. } else {
  758. DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
  759. }
  760. }
  761. } else {
  762. // sub element is ready
  763. // TODO: It is a design flaw that we need to do this here, isn't it?
  764. // DBG_VERBOSE(printf("UA_NodeSetAlias clears %p\n", (void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
  765. // s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  766. }
  767. return UA_SUCCESS;
  768. }
  769. UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSetAliases* dst, _Bool isStart) {
  770. DBG_VERBOSE(printf("UA_NodeSetALiases entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  771. if (isStart) {
  772. if (dst == UA_NULL) {
  773. UA_NodeSetAliases_new(&dst);
  774. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  775. }
  776. s->parent[s->depth].len = 0;
  777. XML_Stack_addChildHandler(s, "Alias", strlen("Alias"), (XML_decoder) UA_NodeSetAlias_decodeXML, UA_INVALIDTYPE, UA_NULL);
  778. } else {
  779. // sub element is ready, add to array
  780. if (dst->size < 0 || dst->size == 0) {
  781. dst->size = 1;
  782. UA_alloc((void** )&(dst->aliases), dst->size * sizeof(UA_NodeSetAlias*));
  783. DBG_VERBOSE(
  784. printf("allocate aliases:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->aliases),
  785. dst->size));
  786. } else {
  787. dst->size++;
  788. dst->aliases = realloc(dst->aliases, dst->size * sizeof(UA_NodeSetAlias*));
  789. DBG_VERBOSE(
  790. printf("reallocate aliases:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->aliases),
  791. dst->size));
  792. }
  793. // index starts with 0, therefore size-1
  794. DBG_VERBOSE(printf("assign alias:dst=%p, src=%p\n", (void* )dst->aliases[dst->size - 1], (void* )attr));
  795. dst->aliases[dst->size - 1] = (UA_NodeSetAlias*) attr;
  796. DBG_VERBOSE(printf("UA_NodeSetAliases clears %p\n", (void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
  797. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  798. }
  799. return UA_SUCCESS;
  800. }
  801. UA_Int32 UA_NodeSet_decodeXML(XML_Stack* s, XML_Attr* attr, UA_NodeSet* dst, _Bool isStart) {
  802. DBG_VERBOSE(printf("UA_NodeSet entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
  803. if (isStart) {
  804. if (dst == UA_NULL) {
  805. UA_NodeSet_new(&dst, 99); // we don't really need the namespaceid for this..'
  806. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
  807. }
  808. s->parent[s->depth].len = 0;
  809. XML_Stack_addChildHandler(s, "Aliases", strlen("Aliases"), (XML_decoder) UA_NodeSetAliases_decodeXML, UA_INVALIDTYPE,
  810. &(dst->aliases));
  811. XML_Stack_addChildHandler(s, "UADataType", strlen("UADataType"), (XML_decoder) UA_DataTypeNode_decodeXML, UA_DATATYPENODE, UA_NULL);
  812. XML_Stack_addChildHandler(s, "UAVariableType", strlen("UAVariableType"), (XML_decoder) UA_VariableTypeNode_decodeXML, UA_VARIABLETYPENODE, UA_NULL);
  813. XML_Stack_addChildHandler(s, "UAVariable", strlen("UAVariable"), (XML_decoder) UA_VariableNode_decodeXML, UA_VARIABLENODE, UA_NULL);
  814. XML_Stack_addChildHandler(s, "UAObjectType", strlen("UAObjectType"), (XML_decoder) UA_ObjectTypeNode_decodeXML, UA_OBJECTTYPENODE, UA_NULL);
  815. XML_Stack_addChildHandler(s, "UAObject", strlen("UAObject"), (XML_decoder) UA_ObjectNode_decodeXML, UA_OBJECTNODE, UA_NULL);
  816. } else {
  817. if (s->parent[s->depth - 1].activeChild == 0 && attr != UA_NULL) {
  818. UA_NodeSetAliases* aliases = (UA_NodeSetAliases*) attr;
  819. DBG(printf("UA_NodeSet_decodeXML - finished aliases: aliases=%p, size=%d\n",(void*)aliases,(aliases==UA_NULL)?-1:aliases->size));
  820. s->aliases = aliases;
  821. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  822. } else if (attr != UA_NULL && (s->parent[s->depth - 1].activeChild == 3 || s->parent[s->depth - 1].activeChild == 5)) {
  823. UA_Node* node = (UA_Node*) attr;
  824. DBG(printf("UA_NodeSet_decodeXML - finished node: node=%p\n", (void* )node));
  825. Namespace_insert(dst->ns, node);
  826. DBG(printf("UA_NodeSet_decodeXML - Inserting "));
  827. DBG(print_node(node));
  828. s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
  829. }
  830. }
  831. return UA_SUCCESS;
  832. }
  833. /** lookup if element is a known child of parent, if yes go for it otherwise ignore */
  834. void XML_Stack_startElement(void * data, const char *el, const char **attr) {
  835. XML_Stack* s = (XML_Stack*) data;
  836. int i;
  837. // scan expected children
  838. XML_Parent* cp = &s->parent[s->depth];
  839. for (i = 0; i < cp->len; i++) {
  840. if (0 == strncmp(cp->children[i].name, el, cp->children[i].length)) {
  841. DBG_VERBOSE(XML_Stack_print(s));
  842. DBG_VERBOSE(printf("%s - processing\n", el));
  843. cp->activeChild = i;
  844. s->depth++;
  845. s->parent[s->depth].name = el;
  846. s->parent[s->depth].len = 0;
  847. s->parent[s->depth].textAttribIdx = -1;
  848. s->parent[s->depth].activeChild = -1;
  849. // finally call the elementHandler and return
  850. cp->children[i].elementHandler(data, attr, cp->children[i].obj, TRUE);
  851. return;
  852. }
  853. }
  854. // if we come here we rejected the processing of el
  855. DBG_VERBOSE(XML_Stack_print(s));
  856. DBG_VERBOSE(printf("%s - rejected\n", el));
  857. s->depth++;
  858. s->parent[s->depth].name = el;
  859. // this should be sufficient to reject the children as well
  860. s->parent[s->depth].len = 0;
  861. }
  862. UA_Int32 XML_isSpace(cstring s, int len) {
  863. int i;
  864. for (i = 0; i < len; i++) {
  865. if (!isspace(s[i])) {
  866. return UA_FALSE;
  867. }
  868. }
  869. return UA_TRUE;
  870. }
  871. /* simulates startElement, endElement behaviour */
  872. void XML_Stack_handleText(void * data, const char *txt, int len) {
  873. XML_Stack* s = (XML_Stack*) data;
  874. if (len > 0 && !XML_isSpace(txt, len)) {
  875. XML_Parent* cp = &(s->parent[s->depth]);
  876. if (cp->textAttribIdx >= 0) {
  877. cp->activeChild = cp->textAttribIdx;
  878. char* buf; // need to copy txt to add 0 as string terminator
  879. UA_alloc((void** )&buf, len + 1);
  880. strncpy(buf, txt, len);
  881. buf[len] = 0;
  882. XML_Attr attr[3] = { cp->textAttrib, buf, UA_NULL };
  883. DBG(printf("handleText @ %s calls start elementHandler %s with dst=%p, buf={%s}\n", XML_Stack_path(s),cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj, buf));
  884. cp->children[cp->activeChild].elementHandler(s, attr, cp->children[cp->activeChild].obj, TRUE);
  885. // FIXME: The indices of this call are simply wrong
  886. // DBG_VERBOSE(printf("handleText calls finish elementHandler %s with dst=%p, attr=(nil)\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj));
  887. // cp->children[cp->activeChild].elementHandler(s, UA_NULL, cp->children[cp->activeChild].obj, FALSE);
  888. if (s->parent[s->depth-1].activeChild > 0) {
  889. // FIXME: actually we'd like to have something like the following, won't we?
  890. // XML_Stack_endElement(data, cp->children[cp->activeChild].name);
  891. XML_child* c = &(s->parent[s->depth-1].children[s->parent[s->depth-1].activeChild]);
  892. c->elementHandler(s, UA_NULL, c->obj, FALSE);
  893. }
  894. UA_free(buf);
  895. } else {
  896. DBG_VERBOSE(XML_Stack_print(s));
  897. DBG_VERBOSE(printf("textData - ignore text data '%.*s'\n", len, txt));
  898. }
  899. }
  900. }
  901. /** if we are an activeChild of a parent we call the child-handler */
  902. void XML_Stack_endElement(void *data, const char *el) {
  903. XML_Stack* s = (XML_Stack*) data;
  904. // the parent of the parent (pop) of the element knows the elementHandler, therefore depth-2!
  905. if (s->depth > 1) {
  906. // inform parents elementHandler that everything is done
  907. XML_Parent* cp = &(s->parent[s->depth - 1]);
  908. XML_Parent* cpp = &(s->parent[s->depth - 2]);
  909. if (cpp->activeChild >= 0 && cp->activeChild >= 0) {
  910. DBG_VERBOSE(XML_Stack_print(s));
  911. DBG_VERBOSE(
  912. printf(" - inform pop %s, arg=%p\n", cpp->children[cpp->activeChild].name,
  913. (void* ) cp->children[cp->activeChild].obj));
  914. cpp->children[cpp->activeChild].elementHandler(s, (XML_Attr*) cp->children[cp->activeChild].obj,
  915. cpp->children[cpp->activeChild].obj, FALSE);
  916. }
  917. // reset
  918. cp->activeChild = -1;
  919. }
  920. s->depth--;
  921. }
  922. UA_Int32 Namespace_loadFromFile(Namespace **ns,UA_UInt32 namespaceId,const char* rootName,const char* fileName) {
  923. int f;
  924. if (fileName == UA_NULL)
  925. f = 0; // stdin
  926. else if ((f= open(fileName, O_RDONLY)) == -1)
  927. return UA_ERR_INVALID_VALUE;
  928. char buf[1024];
  929. int len; /* len is the number of bytes in the current bufferful of data */
  930. XML_Stack s;
  931. XML_Stack_init(&s, rootName);
  932. UA_NodeSet n;
  933. UA_NodeSet_init(&n, 0);
  934. XML_Stack_addChildHandler(&s, "UANodeSet", strlen("UANodeSet"), (XML_decoder) UA_NodeSet_decodeXML, UA_INVALIDTYPE, &n);
  935. XML_Parser parser = XML_ParserCreate(NULL);
  936. XML_SetUserData(parser, &s);
  937. XML_SetElementHandler(parser, XML_Stack_startElement, XML_Stack_endElement);
  938. XML_SetCharacterDataHandler(parser, XML_Stack_handleText);
  939. while ((len = read(f, buf, 1024)) > 0) {
  940. if (!XML_Parse(parser, buf, len, (len < 1024))) {
  941. return 1;
  942. }
  943. }
  944. XML_ParserFree(parser);
  945. close(f);
  946. DBG_VERBOSE(printf("Namespace_loadFromFile - aliases addr=%p, size=%d\n", (void*) &(n.aliases), n.aliases.size));
  947. DBG_VERBOSE(UA_NodeSetAliases_println("Namespace_loadFromFile - elements=", &n.aliases));
  948. // eventually return the namespace object that has been allocated in UA_NodeSet_init
  949. *ns = n.ns;
  950. return UA_SUCCESS;
  951. }