ua_types.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. #include <stdarg.h> // va_start, va_end
  2. #include <time.h>
  3. #ifdef WIN32
  4. #include <windows.h>
  5. #else
  6. #include <sys/time.h>
  7. #endif
  8. #ifdef DEBUG
  9. #include <stdio.h>
  10. #endif
  11. #include "util/ua_util.h"
  12. #include "ua_types.h"
  13. #include "ua_types_encoding_binary.h"
  14. #include "ua_namespace_0.h"
  15. /* Boolean */
  16. void UA_Boolean_init(UA_Boolean *p) {
  17. if(!p) return;
  18. *p = UA_FALSE;
  19. }
  20. UA_TYPE_DELETE_DEFAULT(UA_Boolean)
  21. UA_TYPE_DELETEMEMBERS_NOACTION(UA_Boolean)
  22. UA_TYPE_NEW_DEFAULT(UA_Boolean)
  23. UA_TYPE_COPY_DEFAULT(UA_Boolean)
  24. #ifdef DEBUG
  25. void UA_Boolean_print(const UA_Boolean *p, FILE *stream) {
  26. if(p == UA_NULL || stream == UA_NULL) return;
  27. if(*p) fprintf(stream, "UA_TRUE");
  28. else fprintf(stream, "UA_FALSE");
  29. }
  30. #endif
  31. /* SByte */
  32. UA_TYPE_DEFAULT(UA_SByte)
  33. #ifdef DEBUG
  34. void UA_SByte_print(const UA_SByte *p, FILE *stream) {
  35. if(p == UA_NULL || stream == UA_NULL) return;
  36. UA_SByte x = *p;
  37. fprintf(stream, "%s%x\n", x < 0 ? "-" : "", x < 0 ? -x : x);
  38. }
  39. #endif
  40. /* Byte */
  41. UA_TYPE_DEFAULT(UA_Byte)
  42. #ifdef DEBUG
  43. void UA_Byte_print(const UA_Byte *p, FILE *stream) {
  44. if(p == UA_NULL || stream == UA_NULL) return;
  45. fprintf(stream, "%x", *p);
  46. }
  47. #endif
  48. /* Int16 */
  49. UA_TYPE_DEFAULT(UA_Int16)
  50. #ifdef DEBUG
  51. void UA_Int16_print(const UA_Int16 *p, FILE *stream) {
  52. if(p == UA_NULL || stream == UA_NULL) return;
  53. fprintf(stream, "%d", *p);
  54. }
  55. #endif
  56. /* UInt16 */
  57. UA_TYPE_DEFAULT(UA_UInt16)
  58. #ifdef DEBUG
  59. void UA_UInt16_print(const UA_UInt16 *p, FILE *stream) {
  60. if(p == UA_NULL || stream == UA_NULL) return;
  61. fprintf(stream, "%u", *p);
  62. }
  63. #endif
  64. /* Int32 */
  65. UA_TYPE_DEFAULT(UA_Int32)
  66. #ifdef DEBUG
  67. void UA_Int32_print(const UA_Int32 *p, FILE *stream) {
  68. if(p == UA_NULL || stream == UA_NULL) return;
  69. fprintf(stream, "%d", *p);
  70. }
  71. #endif
  72. /* UInt32 */
  73. UA_TYPE_DEFAULT(UA_UInt32)
  74. #ifdef DEBUG
  75. void UA_UInt32_print(const UA_UInt32 *p, FILE *stream) {
  76. if(p == UA_NULL || stream == UA_NULL) return;
  77. fprintf(stream, "%u", *p);
  78. }
  79. #endif
  80. /* Int64 */
  81. UA_TYPE_DEFAULT(UA_Int64)
  82. #ifdef DEBUG
  83. void UA_Int64_print(const UA_Int64 *p, FILE *stream) {
  84. if(p == UA_NULL || stream == UA_NULL) return;
  85. fprintf(stream, "%" PRIi64, *p);
  86. }
  87. #endif
  88. /* UInt64 */
  89. UA_TYPE_DEFAULT(UA_UInt64)
  90. #ifdef DEBUG
  91. void UA_UInt64_print(const UA_UInt64 *p, FILE *stream) {
  92. if(p == UA_NULL || stream == UA_NULL) return;
  93. fprintf(stream, "%" PRIu64, *p);
  94. }
  95. #endif
  96. /* Float */
  97. UA_TYPE_DEFAULT(UA_Float)
  98. #ifdef DEBUG
  99. void UA_Float_print(const UA_Float *p, FILE *stream) {
  100. if(p == UA_NULL || stream == UA_NULL) return;
  101. fprintf(stream, "%f", *p);
  102. }
  103. #endif
  104. /* Double */
  105. UA_TYPE_DEFAULT(UA_Double)
  106. #ifdef DEBUG
  107. void UA_Double_print(const UA_Double *p, FILE *stream) {
  108. if(p == UA_NULL || stream == UA_NULL) return;
  109. fprintf(stream, "%f", *p);
  110. }
  111. #endif
  112. /* String */
  113. UA_TYPE_NEW_DEFAULT(UA_String)
  114. void UA_String_init(UA_String *p) {
  115. if(!p) return;
  116. p->length = -1;
  117. p->data = UA_NULL;
  118. }
  119. UA_TYPE_DELETE_DEFAULT(UA_String)
  120. void UA_String_deleteMembers(UA_String *p) {
  121. if(p && p->length > 0 && p->data != UA_NULL) {
  122. UA_free(p->data);
  123. UA_String_init(p);
  124. }
  125. }
  126. UA_Int32 UA_String_copy(UA_String const *src, UA_String *dst) {
  127. UA_Int32 retval = UA_SUCCESS;
  128. if(!src || !dst) return UA_ERROR;
  129. if(src->length > 0) {
  130. retval |= UA_alloc((void **)&dst->data, src->length);
  131. if(retval != UA_SUCCESS)
  132. return retval;
  133. UA_memcpy((void *)dst->data, src->data, src->length);
  134. }
  135. dst->length = src->length;
  136. return retval;
  137. }
  138. #ifdef DEBUG
  139. void UA_String_print(const UA_String *p, FILE *stream) {
  140. if(p == UA_NULL || stream == UA_NULL) return;
  141. fprintf(stream, "(UA_String){%d,", p->length);
  142. if(p->data != UA_NULL)
  143. fprintf(stream, "\"%.*s\"}", p->length, p->data);
  144. else
  145. fprintf(stream, "UA_NULL}");
  146. }
  147. #endif
  148. UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
  149. UA_Int32 retval = UA_SUCCESS;
  150. dst->length = strlen(src);
  151. dst->data = UA_NULL;
  152. if(dst->length > 0) {
  153. retval |= UA_alloc((void **)&dst->data, dst->length);
  154. if(retval == UA_SUCCESS)
  155. UA_memcpy((void *)dst->data, src, dst->length);
  156. }
  157. return retval;
  158. }
  159. #define UA_STRING_COPYPRINTF_BUFSIZE 1024
  160. UA_Int32 UA_String_copyprintf(char const *fmt, UA_String *dst, ...) {
  161. UA_Int32 retval = UA_SUCCESS;
  162. char src[UA_STRING_COPYPRINTF_BUFSIZE];
  163. UA_Int32 len;
  164. va_list ap;
  165. va_start(ap, dst);
  166. #pragma GCC diagnostic push
  167. #pragma GCC diagnostic ignored "-Wformat-nonliteral"
  168. // vsnprintf should only take a literal and no variable to be secure
  169. len = vsnprintf(src, UA_STRING_COPYPRINTF_BUFSIZE, fmt, ap);
  170. #pragma GCC diagnostic pop
  171. va_end(ap);
  172. if(len < 0) { // FIXME: old glibc 2.0 would return -1 when truncated
  173. dst->length = 0;
  174. dst->data = UA_NULL;
  175. retval = UA_ERR_INVALID_VALUE;
  176. } else {
  177. // since glibc 2.1 vsnprintf returns len that would have resulted if buf were large enough
  178. dst->length = ( len > UA_STRING_COPYPRINTF_BUFSIZE ? UA_STRING_COPYPRINTF_BUFSIZE : len );
  179. retval |= UA_alloc((void **)&dst->data, dst->length);
  180. if(retval == UA_SUCCESS)
  181. UA_memcpy((void *)dst->data, src, dst->length);
  182. }
  183. return retval;
  184. }
  185. UA_EQUALITY UA_String_equal(const UA_String *string1, const UA_String *string2) {
  186. if(string1->length <= 0 && string2->length <= 0)
  187. return UA_EQUAL;
  188. if(string1->length != string2->length)
  189. return UA_NOT_EQUAL;
  190. // casts are needed to overcome signed warnings
  191. UA_Int32 is = strncmp((char const *)string1->data, (char const *)string2->data, string1->length);
  192. return (is == 0) ? UA_EQUAL : UA_NOT_EQUAL;
  193. }
  194. #ifdef DEBUG
  195. void UA_String_printf(char const *label, const UA_String *string) {
  196. printf("%s {Length=%d, Data=%.*s}\n", label, string->length,
  197. string->length, (char *)string->data);
  198. }
  199. #endif
  200. #ifdef DEBUG
  201. void UA_String_printx(char const *label, const UA_String *string) {
  202. if(string == UA_NULL) {
  203. printf("%s {NULL}\n", label); return;
  204. }
  205. printf("%s {Length=%d, Data=", label, string->length);
  206. if(string->length > 0) {
  207. for(UA_Int32 i = 0;i < string->length;i++) {
  208. printf("%c%d", i == 0 ? '{' : ',', (string->data)[i]);
  209. // if (i > 0 && !(i%20)) { printf("\n\t"); }
  210. }
  211. } else
  212. printf("{");
  213. printf("}}\n");
  214. }
  215. #endif
  216. #ifdef DEBUG
  217. void UA_String_printx_hex(char const *label, const UA_String *string) {
  218. printf("%s {Length=%d, Data=", label, string->length);
  219. if(string->length > 0) {
  220. for(UA_Int32 i = 0;i < string->length;i++)
  221. printf("%c%x", i == 0 ? '{' : ',', (string->data)[i]);
  222. } else
  223. printf("{");
  224. printf("}}\n");
  225. }
  226. #endif
  227. /* DateTime */
  228. UA_TYPE_AS(UA_DateTime, UA_Int64)
  229. // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
  230. #define FILETIME_UNIXTIME_BIAS_SEC 11644473600LL
  231. // Factors
  232. #define HUNDRED_NANOSEC_PER_USEC 10LL
  233. #define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
  234. #ifdef MSVC
  235. static const unsigned __int64 epoch = 116444736000000000;
  236. int gettimeofday(struct timeval *tp, struct timezone *tzp) {
  237. FILETIME ft;
  238. SYSTEMTIME st;
  239. ULARGE_INTEGER ul;
  240. GetSystemTime(&st);
  241. SystemTimeToFileTime(&st, &ft);
  242. ul.LowPart = ft.dwLowDateTime;
  243. ul.HighPart = ft.dwHighDateTime;
  244. tp->tv_sec = (ul.QuadPart - epoch) / 10000000L;
  245. tp->tv_usec = st.wMilliseconds * 1000;
  246. return 0;
  247. }
  248. #endif
  249. // IEC 62541-6 §5.2.2.5 A DateTime value shall be encoded as a 64-bit signed integer
  250. // which represents the number of 100 nanosecond intervals since January 1, 1601 (UTC).
  251. UA_DateTime UA_DateTime_now() {
  252. UA_DateTime dateTime;
  253. struct timeval tv;
  254. gettimeofday(&tv, UA_NULL);
  255. dateTime = (tv.tv_sec + FILETIME_UNIXTIME_BIAS_SEC)
  256. * HUNDRED_NANOSEC_PER_SEC + tv.tv_usec * HUNDRED_NANOSEC_PER_USEC;
  257. return dateTime;
  258. }
  259. UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time) {
  260. UA_DateTimeStruct dateTimeStruct;
  261. //calcualting the the milli-, micro- and nanoseconds
  262. UA_DateTime timeTemp;
  263. timeTemp = (time-((time/10)*10))*100; //getting the last digit -> *100 for the 100 nanaseconds resolution
  264. dateTimeStruct.nanoSec = timeTemp; //123 456 7 -> 700 nanosec;
  265. timeTemp = (time-((time/10000)*10000))/10;
  266. dateTimeStruct.microSec = timeTemp; //123 456 7 -> 456 microsec
  267. timeTemp = (time-((time/10000000)*10000000))/10000;
  268. dateTimeStruct.milliSec = timeTemp; //123 456 7 -> 123 millisec
  269. //calculating the unix time with #include <time.h>
  270. time_t timeInSec = time/10000000; //converting the nanoseconds time in unixtime
  271. struct tm ts;
  272. ts = *gmtime(&timeInSec);
  273. dateTimeStruct.sec = ts.tm_sec;
  274. dateTimeStruct.min = ts.tm_min;
  275. dateTimeStruct.hour = ts.tm_hour;
  276. dateTimeStruct.day = ts.tm_mday;
  277. dateTimeStruct.mounth = ts.tm_mon+1;
  278. dateTimeStruct.year = ts.tm_year + 1900;
  279. return dateTimeStruct;
  280. }
  281. UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String *timeString) {
  282. char *charBuf = (char *)(*timeString).data;
  283. UA_DateTimeStruct tSt = UA_DateTime_toStruct(time);
  284. sprintf(charBuf, "%2d/%2d/%4d %2d:%2d:%2d.%3d.%3d.%3d", tSt.mounth, tSt.day, tSt.year,
  285. tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
  286. return UA_SUCCESS;
  287. }
  288. /* Guid */
  289. UA_TYPE_DELETE_DEFAULT(UA_Guid)
  290. UA_TYPE_DELETEMEMBERS_NOACTION(UA_Guid)
  291. UA_EQUALITY UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
  292. if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
  293. return UA_EQUAL;
  294. return UA_NOT_EQUAL;
  295. }
  296. void UA_Guid_init(UA_Guid *p) {
  297. if(!p) return;
  298. p->data1 = 0;
  299. p->data2 = 0;
  300. p->data3 = 0;
  301. memset(p->data4, 0, sizeof(UA_Byte)*8);
  302. }
  303. UA_TYPE_NEW_DEFAULT(UA_Guid)
  304. UA_Int32 UA_Guid_copy(UA_Guid const *src, UA_Guid *dst) {
  305. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  306. UA_memcpy((void *)dst, (void *)src, sizeof(UA_Guid));
  307. return UA_SUCCESS;
  308. }
  309. #ifdef DEBUG
  310. void UA_Guid_print(const UA_Guid *p, FILE *stream) {
  311. if(p == UA_NULL || stream == UA_NULL) return;
  312. fprintf(stream, "(UA_Guid){%u, %u %u {%x,%x,%x,%x,%x,%x,%x,%x}}", p->data1, p->data2, p->data3,
  313. p->data4[0],
  314. p->data4[1], p->data4[2], p->data4[3], p->data4[4], p->data4[5], p->data4[6], p->data4[7]);
  315. }
  316. #endif
  317. /* ByteString */
  318. UA_TYPE_AS(UA_ByteString, UA_String)
  319. UA_EQUALITY UA_ByteString_equal(const UA_ByteString *string1, const UA_ByteString *string2) {
  320. return UA_String_equal((const UA_String *)string1, (const UA_String *)string2);
  321. }
  322. #ifdef DEBUG
  323. void UA_ByteString_printf(char *label, const UA_ByteString *string) {
  324. UA_String_printf(label, (UA_String *)string);
  325. }
  326. #endif
  327. #ifdef DEBUG
  328. void UA_ByteString_printx(char *label, const UA_ByteString *string) {
  329. UA_String_printx(label, (UA_String *)string);
  330. }
  331. #endif
  332. #ifdef DEBUG
  333. void UA_ByteString_printx_hex(char *label, const UA_ByteString *string) {
  334. UA_String_printx_hex(label, (UA_String *)string);
  335. }
  336. #endif
  337. UA_Byte UA_Byte_securityPoliceNoneData[] = "http://opcfoundation.org/UA/SecurityPolicy#None";
  338. // sizeof()-1 : discard the implicit null-terminator of the c-char-string
  339. UA_ByteString UA_ByteString_securityPoliceNone =
  340. { sizeof(UA_Byte_securityPoliceNoneData)-1, UA_Byte_securityPoliceNoneData };
  341. UA_Int32 UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length) {
  342. UA_Int32 retval = UA_SUCCESS;
  343. if(length > 0 && (retval |= UA_alloc((void **)&p->data, length)) == UA_SUCCESS)
  344. p->length = length;
  345. else {
  346. p->length = -1;
  347. p->data = UA_NULL;
  348. }
  349. return retval;
  350. }
  351. /* XmlElement */
  352. UA_TYPE_AS(UA_XmlElement, UA_ByteString)
  353. /* NodeId */
  354. void UA_NodeId_init(UA_NodeId *p) {
  355. if(!p) return;
  356. p->identifierType = UA_NODEIDTYPE_NUMERIC;
  357. p->namespaceIndex = 0;
  358. memset(&p->identifier, 0, sizeof(p->identifier));
  359. }
  360. UA_TYPE_NEW_DEFAULT(UA_NodeId)
  361. UA_Int32 UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst) {
  362. UA_Int32 retval = UA_SUCCESS;
  363. if(src == UA_NULL || dst == UA_NULL)
  364. return UA_ERROR;
  365. switch(src->identifierType) {
  366. case UA_NODEIDTYPE_NUMERIC:
  367. *dst = *src;
  368. return UA_SUCCESS;
  369. break;
  370. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  371. retval |= UA_String_copy(&src->identifier.string, &dst->identifier.string);
  372. break;
  373. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  374. retval |= UA_Guid_copy(&src->identifier.guid, &dst->identifier.guid);
  375. break;
  376. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  377. retval |= UA_ByteString_copy(&src->identifier.byteString, &dst->identifier.byteString);
  378. break;
  379. }
  380. dst->identifierType = src->identifierType;
  381. return retval;
  382. }
  383. UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id) {
  384. return id->namespaceIndex == 0 &&
  385. id->identifierType == UA_NODEIDTYPE_NUMERIC &&
  386. id->identifier.numeric <= UA_DIAGNOSTICINFO;
  387. }
  388. UA_TYPE_DELETE_DEFAULT(UA_NodeId)
  389. void UA_NodeId_deleteMembers(UA_NodeId *p) {
  390. if(!p) return;
  391. switch(p->identifierType) {
  392. case UA_NODEIDTYPE_NUMERIC:
  393. // nothing to do
  394. break;
  395. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  396. UA_String_deleteMembers(&p->identifier.string);
  397. break;
  398. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  399. UA_Guid_deleteMembers(&p->identifier.guid);
  400. break;
  401. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  402. UA_ByteString_deleteMembers(&p->identifier.byteString);
  403. break;
  404. }
  405. }
  406. #ifdef DEBUG
  407. void UA_NodeId_print(const UA_NodeId *p, FILE *stream) {
  408. if(p == UA_NULL || stream == UA_NULL)
  409. return;
  410. fprintf(stream, "(UA_NodeId){");
  411. switch(p->identifierType) {
  412. case UA_NODEIDTYPE_NUMERIC:
  413. fprintf(stream, "UA_NODEIDTYPE_NUMERIC");
  414. break;
  415. case UA_NODEIDTYPE_STRING:
  416. fprintf(stream, "UA_NODEIDTYPE_STRING");
  417. break;
  418. case UA_NODEIDTYPE_BYTESTRING:
  419. fprintf(stream, "UA_NODEIDTYPE_BYTESTRING");
  420. break;
  421. case UA_NODEIDTYPE_GUID:
  422. fprintf(stream, "UA_NODEIDTYPE_GUID");
  423. break;
  424. default:
  425. fprintf(stream, "ERROR");
  426. break;
  427. }
  428. fprintf(stream, ",%u,", p->namespaceIndex);
  429. switch(p->identifierType & UA_NODEIDTYPE_MASK) {
  430. case UA_NODEIDTYPE_NUMERIC:
  431. fprintf(stream, ".identifier.numeric=%u", p->identifier.numeric);
  432. break;
  433. case UA_NODEIDTYPE_STRING:
  434. fprintf(stream, ".identifier.string=%.*s", p->identifier.string.length, p->identifier.string.data);
  435. break;
  436. case UA_NODEIDTYPE_BYTESTRING:
  437. fprintf(stream, ".identifier.byteString=%.*s", p->identifier.byteString.length,
  438. p->identifier.byteString.data);
  439. break;
  440. case UA_NODEIDTYPE_GUID:
  441. fprintf(stream, ".identifer.guid=");
  442. UA_Guid_print(&p->identifier.guid, stream);
  443. break;
  444. default:
  445. fprintf(stream, "ERROR");
  446. break;
  447. }
  448. fprintf(stream, "}");
  449. }
  450. #endif
  451. UA_EQUALITY UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
  452. if(n1 == UA_NULL || n2 == UA_NULL || n1->namespaceIndex != n2->namespaceIndex)
  453. return UA_NOT_EQUAL;
  454. switch(n1->identifierType) {
  455. case UA_NODEIDTYPE_NUMERIC:
  456. if(n1->identifier.numeric == n2->identifier.numeric)
  457. return UA_EQUAL;
  458. else
  459. return UA_NOT_EQUAL;
  460. case UA_NODEIDTYPE_STRING:
  461. return UA_String_equal(&n1->identifier.string, &n2->identifier.string);
  462. case UA_NODEIDTYPE_GUID:
  463. return UA_Guid_equal(&n1->identifier.guid, &n2->identifier.guid);
  464. case UA_NODEIDTYPE_BYTESTRING:
  465. return UA_ByteString_equal(&n1->identifier.byteString, &n2->identifier.byteString);
  466. }
  467. return UA_NOT_EQUAL;
  468. }
  469. UA_Boolean UA_NodeId_isNull(const UA_NodeId *p) {
  470. switch(p->identifierType) {
  471. case UA_NODEIDTYPE_NUMERIC:
  472. if(p->namespaceIndex != 0 || p->identifier.numeric != 0) return UA_FALSE;
  473. break;
  474. case UA_NODEIDTYPE_STRING:
  475. if(p->namespaceIndex != 0 || p->identifier.string.length != 0) return UA_FALSE;
  476. break;
  477. case UA_NODEIDTYPE_GUID:
  478. if(p->namespaceIndex != 0 ||
  479. memcmp(&p->identifier.guid, (char[sizeof(UA_Guid)]) { 0 }, sizeof(UA_Guid)) != 0) return UA_FALSE;
  480. break;
  481. case UA_NODEIDTYPE_BYTESTRING:
  482. if(p->namespaceIndex != 0 || p->identifier.byteString.length != 0) return UA_FALSE;
  483. break;
  484. default:
  485. return UA_FALSE;
  486. }
  487. return UA_TRUE;
  488. }
  489. /* ExpandedNodeId */
  490. UA_TYPE_DELETE_DEFAULT(UA_ExpandedNodeId)
  491. void UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p) {
  492. if(!p) return;
  493. UA_NodeId_deleteMembers(&p->nodeId);
  494. UA_String_deleteMembers(&p->namespaceUri);
  495. }
  496. void UA_ExpandedNodeId_init(UA_ExpandedNodeId *p) {
  497. if(!p) return;
  498. UA_NodeId_init(&p->nodeId);
  499. UA_String_init(&p->namespaceUri);
  500. p->serverIndex = 0;
  501. }
  502. UA_TYPE_NEW_DEFAULT(UA_ExpandedNodeId)
  503. UA_Int32 UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst) {
  504. UA_Int32 retval = UA_SUCCESS;
  505. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  506. UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
  507. UA_NodeId_copy(&src->nodeId, &dst->nodeId);
  508. UA_UInt32_copy(&src->serverIndex, &dst->serverIndex);
  509. return retval;
  510. }
  511. #ifdef DEBUG
  512. void UA_ExpandedNodeId_print(const UA_ExpandedNodeId *p, FILE *stream) {
  513. if(p == UA_NULL || stream == UA_NULL) return;
  514. fprintf(stream, "(UA_ExpandedNodeId){");
  515. UA_NodeId_print(&p->nodeId, stream);
  516. fprintf(stream, ",");
  517. UA_String_print(&p->namespaceUri, stream);
  518. fprintf(stream, ",");
  519. UA_UInt32_print(&p->serverIndex, stream);
  520. fprintf(stream, "}");
  521. }
  522. #endif
  523. UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p) {
  524. return UA_NodeId_isNull(&p->nodeId);
  525. }
  526. /* StatusCode */
  527. UA_TYPE_AS(UA_StatusCode, UA_UInt32)
  528. /* QualifiedName */
  529. UA_TYPE_DELETE_DEFAULT(UA_QualifiedName)
  530. void UA_QualifiedName_deleteMembers(UA_QualifiedName *p) {
  531. if(!p) return;
  532. UA_String_deleteMembers(&p->name);
  533. }
  534. void UA_QualifiedName_init(UA_QualifiedName *p) {
  535. if(!p) return;
  536. UA_String_init(&p->name);
  537. p->namespaceIndex = 0;
  538. }
  539. UA_TYPE_NEW_DEFAULT(UA_QualifiedName)
  540. UA_Int32 UA_QualifiedName_copy(UA_QualifiedName const *src, UA_QualifiedName *dst) {
  541. UA_Int32 retval = UA_SUCCESS;
  542. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  543. retval |= UA_String_copy(&src->name, &dst->name);
  544. retval |= UA_UInt16_copy(&src->namespaceIndex, &dst->namespaceIndex);
  545. return retval;
  546. }
  547. UA_Int32 UA_QualifiedName_copycstring(char const *src, UA_QualifiedName *dst) {
  548. dst->namespaceIndex = 0;
  549. return UA_String_copycstring(src, &dst->name);
  550. }
  551. #ifdef DEBUG
  552. void UA_QualifiedName_print(const UA_QualifiedName *p, FILE *stream) {
  553. if(p == UA_NULL || stream == UA_NULL) return;
  554. fprintf(stream, "(UA_QualifiedName){");
  555. UA_UInt16_print(&p->namespaceIndex, stream);
  556. fprintf(stream, ",");
  557. UA_String_print(&p->name, stream);
  558. fprintf(stream, "}");
  559. }
  560. #endif
  561. #ifdef DEBUG
  562. void UA_QualifiedName_printf(char const *label, const UA_QualifiedName *qn) {
  563. printf("%s {NamespaceIndex=%u, Length=%d, Data=%.*s}\n", label, qn->namespaceIndex,
  564. qn->name.length, qn->name.length, (char *)qn->name.data);
  565. }
  566. #endif
  567. /* LocalizedText */
  568. UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
  569. void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
  570. if(!p) return;
  571. UA_String_deleteMembers(&p->locale);
  572. UA_String_deleteMembers(&p->text);
  573. }
  574. void UA_LocalizedText_init(UA_LocalizedText *p) {
  575. if(!p) return;
  576. UA_String_init(&p->locale);
  577. UA_String_init(&p->text);
  578. }
  579. UA_TYPE_NEW_DEFAULT(UA_LocalizedText)
  580. UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst) {
  581. if(dst == UA_NULL) return UA_ERROR;
  582. UA_LocalizedText_init(dst);
  583. UA_Int32 retval = UA_SUCCESS;
  584. retval |= UA_String_copycstring("en", &dst->locale); // TODO: Are language codes upper case?
  585. if(retval != UA_SUCCESS) return retval;
  586. retval |= UA_String_copycstring(src, &dst->text);
  587. return retval;
  588. }
  589. UA_Int32 UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst) {
  590. UA_Int32 retval = UA_SUCCESS;
  591. if(!src || !dst) return UA_ERROR;
  592. UA_LocalizedText_init(dst);
  593. retval |= UA_String_copy(&src->locale, &dst->locale);
  594. if(retval != UA_SUCCESS) return retval;
  595. retval |= UA_String_copy(&src->text, &dst->text);
  596. return retval;
  597. }
  598. #ifdef DEBUG
  599. void UA_LocalizedText_print(const UA_LocalizedText *p, FILE *stream) {
  600. if(p == UA_NULL || stream == UA_NULL) return;
  601. fprintf(stream, "(UA_LocalizedText){");
  602. UA_String_print(&p->locale, stream);
  603. fprintf(stream, ",");
  604. UA_String_print(&p->text, stream);
  605. fprintf(stream, "}");
  606. }
  607. #endif
  608. /* ExtensionObject */
  609. UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
  610. void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
  611. if(!p) return;
  612. UA_NodeId_deleteMembers(&p->typeId);
  613. UA_ByteString_deleteMembers(&p->body);
  614. }
  615. void UA_ExtensionObject_init(UA_ExtensionObject *p) {
  616. if(!p) return;
  617. UA_NodeId_init(&p->typeId);
  618. p->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED;
  619. UA_ByteString_init(&p->body);
  620. }
  621. UA_TYPE_NEW_DEFAULT(UA_ExtensionObject)
  622. UA_Int32 UA_ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst) {
  623. UA_Int32 retval = UA_SUCCESS;
  624. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  625. dst->encoding = src->encoding;
  626. retval |= UA_ByteString_copy(&src->body, &dst->body);
  627. retval |= UA_NodeId_copy(&src->typeId, &dst->typeId);
  628. return retval;
  629. }
  630. #ifdef DEBUG
  631. void UA_ExtensionObject_print(const UA_ExtensionObject *p, FILE *stream) {
  632. if(p == UA_NULL || stream == UA_NULL) return;
  633. fprintf(stream, "(UA_ExtensionObject){");
  634. UA_NodeId_print(&p->typeId, stream);
  635. if(p->encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING)
  636. fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING,");
  637. else if(p->encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML)
  638. fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML,");
  639. else
  640. fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED,");
  641. UA_ByteString_print(&p->body, stream);
  642. fprintf(stream, "}");
  643. }
  644. #endif
  645. /* DataValue */
  646. UA_TYPE_DELETE_DEFAULT(UA_DataValue)
  647. void UA_DataValue_deleteMembers(UA_DataValue *p) {
  648. if(!p) return;
  649. UA_Variant_deleteMembers(&p->value);
  650. }
  651. void UA_DataValue_init(UA_DataValue *p) {
  652. if(!p) return;
  653. p->encodingMask = 0;
  654. p->serverPicoseconds = 0;
  655. UA_DateTime_init(&p->serverTimestamp);
  656. p->sourcePicoseconds = 0;
  657. UA_DateTime_init(&p->sourceTimestamp);
  658. UA_StatusCode_init(&p->status);
  659. UA_Variant_init(&p->value);
  660. }
  661. UA_TYPE_NEW_DEFAULT(UA_DataValue)
  662. UA_Int32 UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst) {
  663. UA_Int32 retval = UA_SUCCESS;
  664. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  665. UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
  666. UA_Int16_copy(&src->serverPicoseconds, &dst->serverPicoseconds);
  667. UA_DateTime_copy(&src->serverTimestamp, &dst->serverTimestamp);
  668. UA_Int16_copy(&src->sourcePicoseconds, &dst->sourcePicoseconds);
  669. UA_DateTime_copy(&src->sourceTimestamp, &dst->sourceTimestamp);
  670. UA_StatusCode_copy(&src->status, &dst->status);
  671. UA_Variant_copy(&src->value, &dst->value);
  672. return retval;
  673. }
  674. #ifdef DEBUG
  675. void UA_DataValue_print(const UA_DataValue *p, FILE *stream) {
  676. if(p == UA_NULL || stream == UA_NULL) return;
  677. fprintf(stream, "(UA_DataValue){");
  678. UA_Byte_print(&p->encodingMask, stream);
  679. fprintf(stream, ",");
  680. UA_Variant_print(&p->value, stream);
  681. fprintf(stream, ",");
  682. UA_StatusCode_print(&p->status, stream);
  683. fprintf(stream, ",");
  684. UA_DateTime_print(&p->sourceTimestamp, stream);
  685. fprintf(stream, ",");
  686. UA_Int16_print(&p->sourcePicoseconds, stream);
  687. fprintf(stream, ",");
  688. UA_DateTime_print(&p->serverTimestamp, stream);
  689. fprintf(stream, ",");
  690. UA_Int16_print(&p->serverPicoseconds, stream);
  691. fprintf(stream, "}");
  692. }
  693. #endif
  694. /* Variant */
  695. UA_TYPE_DELETE_DEFAULT(UA_Variant)
  696. void UA_Variant_deleteMembers(UA_Variant *p) {
  697. if(p->storageType == UA_VARIANT_DATA) {
  698. if(p->storage.data.dataPtr != UA_NULL) {
  699. if(p->storage.data.arrayLength == 1)
  700. p->vt->delete(p->storage.data.dataPtr);
  701. else
  702. UA_Array_delete(p->storage.data.dataPtr, p->storage.data.arrayLength, p->vt);
  703. p->storage.data.dataPtr = UA_NULL;
  704. }
  705. if(p->storage.data.arrayDimensions) {
  706. UA_free(p->storage.data.arrayDimensions);
  707. p->storage.data.arrayDimensions = UA_NULL;
  708. }
  709. return;
  710. }
  711. if(p->storageType == UA_VARIANT_DATASOURCE) {
  712. p->storage.datasource.delete(p->storage.datasource.identifier);
  713. }
  714. }
  715. UA_TYPE_NEW_DEFAULT(UA_Variant)
  716. void UA_Variant_init(UA_Variant *p) {
  717. if(!p) return;
  718. p->storageType = UA_VARIANT_DATA;
  719. p->storage.data.arrayLength = -1; // no element, p->data == UA_NULL
  720. p->storage.data.dataPtr = UA_NULL;
  721. p->storage.data.arrayDimensions = UA_NULL;
  722. p->storage.data.arrayDimensionsLength = -1;
  723. p->vt = &UA_.types[UA_INVALIDTYPE];
  724. }
  725. /** It is not allowed to copy into a variant that points to an external data source. */
  726. UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
  727. if(!src || !dst || dst->storageType == UA_VARIANT_DATASOURCE) return UA_ERROR;
  728. UA_Int32 retval = UA_SUCCESS;
  729. UA_VariantData *dstdata = &dst->storage.data;
  730. const UA_VariantData *srcdata;
  731. if(src->storageType == UA_VARIANT_DATA || src->storageType == UA_VARIANT_DATA_NODELETE)
  732. srcdata = &src->storage.data;
  733. else {
  734. retval |= src->storage.datasource.read(src->storage.datasource.identifier, &srcdata);
  735. if(retval != UA_SUCCESS)
  736. return retval;
  737. }
  738. // now copy from srcdata to dstdata.
  739. dst->vt = src->vt;
  740. retval |= UA_Array_copy(srcdata->dataPtr, srcdata->arrayLength, src->vt, &dstdata->dataPtr);
  741. if(retval != UA_SUCCESS)
  742. goto clean_up;
  743. dstdata->arrayLength = srcdata->arrayLength;
  744. if(srcdata->arrayDimensions != UA_NULL) {
  745. retval |= UA_Array_copy(srcdata->arrayDimensions, srcdata->arrayDimensionsLength, &UA_.types[UA_INT32], (void **)&dstdata->arrayDimensions);
  746. if(retval != UA_SUCCESS)
  747. goto clean_up2;
  748. dstdata->arrayDimensionsLength = srcdata->arrayDimensionsLength;
  749. }
  750. // release the src variant if necessary
  751. if(src->storageType == UA_VARIANT_DATASOURCE)
  752. src->storage.datasource.release(src->storage.datasource.identifier, srcdata);
  753. return retval;
  754. // clean ups are falling through to the "lower levels"
  755. clean_up2:
  756. if(dstdata->arrayDimensions != UA_NULL)
  757. UA_Array_delete(dstdata->dataPtr, dstdata->arrayLength, src->vt);
  758. clean_up:
  759. if(src->storageType == UA_VARIANT_DATASOURCE)
  760. src->storage.datasource.release(src->storage.datasource.identifier, srcdata);
  761. return retval;
  762. }
  763. /** Copies data into a variant. The target variant has always a storagetype UA_VARIANT_DATA */
  764. UA_Int32 UA_Variant_copySetValue(UA_Variant *v, UA_VTable_Entry *vt, const void *value) {
  765. if(v == UA_NULL || vt == UA_NULL || value == UA_NULL)
  766. return UA_ERROR;
  767. UA_Variant_init(v);
  768. v->vt = vt;
  769. v->storage.data.arrayLength = 1; // no array but a single entry
  770. UA_Int32 retval = UA_SUCCESS;
  771. retval |= vt->new(&v->storage.data.dataPtr);
  772. if(retval == UA_SUCCESS)
  773. retval |= vt->copy(value, v->storage.data.dataPtr);
  774. return retval;
  775. }
  776. UA_Int32 UA_Variant_copySetArray(UA_Variant *v, UA_VTable_Entry *vt, UA_Int32 arrayLength,
  777. const void *array) {
  778. if(v == UA_NULL || vt == UA_NULL || array == UA_NULL)
  779. return UA_ERROR;
  780. UA_Variant_init(v);
  781. v->vt = vt;
  782. v->storage.data.arrayLength = arrayLength;
  783. return UA_Array_copy(array, arrayLength, vt, &v->storage.data.dataPtr);
  784. }
  785. #ifdef DEBUG
  786. void UA_Variant_print(const UA_Variant *p, FILE *stream) {
  787. if(p == UA_NULL || stream == UA_NULL) return;
  788. UA_UInt32 ns0id = UA_ns0ToVTableIndex(&p->vt->typeId);
  789. fprintf(stream, "(UA_Variant){/*%s*/", p->vt->name);
  790. if(p->vt == &UA_.types[ns0id])
  791. fprintf(stream, "UA_.types[%d]", ns0id);
  792. else if(p->vt == &UA_borrowed_.types[ns0id])
  793. fprintf(stream, "UA_borrowed_.types[%d]", ns0id);
  794. else
  795. fprintf(stream, "ERROR (not a builtin type)");
  796. UA_Int32_print(&p->arrayLength, stream);
  797. fprintf(stream, ",");
  798. UA_Array_print(p->data, p->arrayLength, p->vt, stream);
  799. fprintf(stream, ",");
  800. UA_Int32_print(&p->arrayDimensionsLength, stream);
  801. fprintf(stream, ",");
  802. UA_Array_print(p->arrayDimensions, p->arrayDimensionsLength, &UA_.types[UA_INT32], stream);
  803. fprintf(stream, "}");
  804. }
  805. #endif
  806. /* DiagnosticInfo */
  807. UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
  808. void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
  809. if(!p) return;
  810. UA_String_deleteMembers(&p->additionalInfo);
  811. if((p->encodingMask & UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO) && p->innerDiagnosticInfo) {
  812. UA_DiagnosticInfo_delete(p->innerDiagnosticInfo);
  813. p->innerDiagnosticInfo = UA_NULL;
  814. }
  815. }
  816. void UA_DiagnosticInfo_init(UA_DiagnosticInfo *p) {
  817. if(!p) return;
  818. UA_String_init(&p->additionalInfo);
  819. p->encodingMask = 0;
  820. p->innerDiagnosticInfo = UA_NULL;
  821. UA_StatusCode_init(&p->innerStatusCode);
  822. p->locale = 0;
  823. p->localizedText = 0;
  824. p->namespaceUri = 0;
  825. p->symbolicId = 0;
  826. }
  827. UA_TYPE_NEW_DEFAULT(UA_DiagnosticInfo)
  828. UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst) {
  829. UA_Int32 retval = UA_SUCCESS;
  830. if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
  831. retval |= UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
  832. retval |= UA_Byte_copy(&src->encodingMask, &dst->encodingMask);
  833. retval |= UA_StatusCode_copy(&src->innerStatusCode, &dst->innerStatusCode);
  834. if(src->innerDiagnosticInfo) {
  835. retval |= UA_alloc((void **)&dst->innerDiagnosticInfo, sizeof(UA_DiagnosticInfo));
  836. if(retval == UA_SUCCESS)
  837. retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
  838. } else
  839. dst->innerDiagnosticInfo = UA_NULL;
  840. retval |= UA_Int32_copy(&src->locale, &dst->locale);
  841. retval |= UA_Int32_copy(&src->localizedText, &dst->localizedText);
  842. retval |= UA_Int32_copy(&src->namespaceUri, &dst->namespaceUri);
  843. retval |= UA_Int32_copy(&src->symbolicId, &dst->symbolicId);
  844. return retval;
  845. }
  846. #ifdef DEBUG
  847. void UA_DiagnosticInfo_print(const UA_DiagnosticInfo *p, FILE *stream) {
  848. if(p == UA_NULL || stream == UA_NULL) return;
  849. fprintf(stream, "(UA_DiagnosticInfo){");
  850. UA_Byte_print(&p->encodingMask, stream);
  851. fprintf(stream, ",");
  852. UA_Int32_print(&p->symbolicId, stream);
  853. fprintf(stream, ",");
  854. UA_Int32_print(&p->namespaceUri, stream);
  855. fprintf(stream, ",");
  856. UA_Int32_print(&p->localizedText, stream);
  857. fprintf(stream, ",");
  858. UA_Int32_print(&p->locale, stream);
  859. fprintf(stream, ",");
  860. UA_String_print(&p->additionalInfo, stream);
  861. fprintf(stream, ",");
  862. UA_StatusCode_print(&p->innerStatusCode, stream);
  863. fprintf(stream, ",");
  864. if(p->innerDiagnosticInfo != UA_NULL) {
  865. fprintf(stream, "&");
  866. UA_DiagnosticInfo_print(p->innerDiagnosticInfo, stream);
  867. } else
  868. fprintf(stream, "UA_NULL");
  869. fprintf(stream, "}");
  870. }
  871. #endif
  872. /* InvalidType */
  873. void UA_InvalidType_delete(UA_InvalidType *p) {
  874. return;
  875. }
  876. void UA_InvalidType_deleteMembers(UA_InvalidType *p) {
  877. return;
  878. }
  879. void UA_InvalidType_init(UA_InvalidType *p) {
  880. return;
  881. }
  882. UA_Int32 UA_InvalidType_copy(UA_InvalidType const *src, UA_InvalidType *dst) {
  883. return UA_ERR_INVALID_VALUE;
  884. }
  885. UA_Int32 UA_InvalidType_new(UA_InvalidType **p) {
  886. return UA_ERR_INVALID_VALUE;
  887. }
  888. #ifdef DEBUG
  889. void UA_InvalidType_print(const UA_InvalidType *p, FILE *stream) {
  890. if(p == UA_NULL || stream == UA_NULL) return;
  891. fprintf(stream, "(UA_InvalidType){ERROR (invalid type)}");
  892. }
  893. #endif
  894. /*********/
  895. /* Array */
  896. /*********/
  897. UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_VTable_Entry *vt) {
  898. if(vt == UA_NULL)
  899. return UA_ERROR;
  900. if(noElements <= 0) {
  901. *p = UA_NULL;
  902. return UA_SUCCESS;
  903. }
  904. // FIXME! Arrays cannot be larger than 2**20.
  905. // This was randomly chosen so that the development VM does not blow up.
  906. if(noElements > 1048576) {
  907. *p = UA_NULL;
  908. return UA_ERROR;
  909. }
  910. UA_Int32 retval = UA_SUCCESS;
  911. retval = UA_alloc(p, vt->memSize * noElements);
  912. if(retval != UA_SUCCESS)
  913. return retval;
  914. UA_Array_init(*p, noElements, vt);
  915. return UA_SUCCESS;
  916. }
  917. void UA_Array_init(void *p, UA_Int32 noElements, UA_VTable_Entry *vt) {
  918. if(!p || !vt) return;
  919. char *cp = (char *)p; // so compilers allow pointer arithmetic
  920. UA_UInt32 memSize = vt->memSize;
  921. for(UA_Int32 i = 0;i<noElements;i++) {
  922. vt->init(cp);
  923. cp += memSize;
  924. }
  925. }
  926. void UA_Array_delete(void *p, UA_Int32 noElements, UA_VTable_Entry *vt) {
  927. if(!p || !vt || noElements <= 0) return;
  928. char *cp = (char *)p; // so compilers allow pointer arithmetic
  929. UA_UInt32 memSize = vt->memSize;
  930. for(UA_Int32 i = 0;i<noElements;i++) {
  931. vt->deleteMembers(cp);
  932. cp += memSize;
  933. }
  934. UA_free(p);
  935. }
  936. UA_Int32 UA_Array_copy(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, void **dst) {
  937. UA_Int32 retval;
  938. if(src == UA_NULL || dst == UA_NULL || vt == UA_NULL)
  939. return UA_ERROR;
  940. retval = UA_Array_new(dst, noElements, vt);
  941. if(retval != UA_SUCCESS) {
  942. *dst = UA_NULL;
  943. return retval;
  944. }
  945. char *csrc = (char *)src; // so compilers allow pointer arithmetic
  946. char *cdst = (char *)*dst;
  947. UA_UInt32 memSize = vt->memSize;
  948. UA_Int32 i = 0;
  949. for(;i < noElements && retval == UA_SUCCESS;i++) {
  950. retval |= vt->copy(csrc, cdst);
  951. csrc += memSize;
  952. cdst += memSize;
  953. }
  954. if(retval != UA_SUCCESS) {
  955. i--; // undo last increase
  956. UA_Array_delete(*dst, i, vt);
  957. *dst = UA_NULL;
  958. }
  959. return retval;
  960. }
  961. #ifdef DEBUG
  962. void UA_Array_print(const void *p, UA_Int32 noElements, UA_VTable_Entry *vt, FILE *stream) {
  963. if(p == UA_NULL || vt == UA_NULL || stream == UA_NULL) return;
  964. fprintf(stream, "(%s){", vt->name);
  965. char *cp = (char *)p; // so compilers allow pointer arithmetic
  966. UA_UInt32 memSize = vt->memSize;
  967. for(UA_Int32 i = 0;i < noElements;i++) {
  968. vt->print(cp, stream);
  969. fprintf(stream, ",");
  970. cp += memSize;
  971. }
  972. }
  973. #endif