ua_types.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. #include <stdarg.h> // va_start, va_end
  2. #include <time.h>
  3. #include <stdio.h> // printf
  4. #include <string.h> // strlen
  5. #define __USE_POSIX
  6. #include <stdlib.h> // malloc, free, rand
  7. #include "ua_util.h"
  8. #ifdef _WIN32
  9. #include <windows.h>
  10. #define RAND(SEED) (UA_UInt32)rand()
  11. #else
  12. #include <sys/time.h>
  13. #define RAND(SEED) (UA_UInt32)rand_r(SEED)
  14. #endif
  15. #include "ua_types.h"
  16. #include "ua_statuscodes.h"
  17. #include "ua_types_generated.h"
  18. /*****************/
  19. /* Helper Macros */
  20. /*****************/
  21. #define UA_TYPE_DEFAULT(TYPE) \
  22. UA_TYPE_NEW_DEFAULT(TYPE) \
  23. UA_TYPE_INIT_DEFAULT(TYPE) \
  24. UA_TYPE_DELETEMEMBERS_NOACTION(TYPE) \
  25. UA_TYPE_DELETE_DEFAULT(TYPE) \
  26. UA_TYPE_COPY_DEFAULT(TYPE) \
  27. #define UA_TYPE_NEW_DEFAULT(TYPE) \
  28. TYPE * TYPE##_new() { \
  29. TYPE *p = UA_malloc(sizeof(TYPE)); \
  30. if(p) TYPE##_init(p); \
  31. return p; \
  32. }
  33. #define UA_TYPE_INIT_DEFAULT(TYPE) \
  34. void TYPE##_init(TYPE * p) { \
  35. *p = (TYPE)0; \
  36. }
  37. #define UA_TYPE_DELETEMEMBERS_NOACTION(TYPE) \
  38. void TYPE##_deleteMembers(TYPE *p) { \
  39. }
  40. #define UA_TYPE_DELETE_DEFAULT(TYPE) \
  41. void TYPE##_delete(TYPE *p) { \
  42. TYPE##_deleteMembers(p); \
  43. UA_free(p); \
  44. }
  45. #define UA_TYPE_COPY_DEFAULT(TYPE) \
  46. UA_StatusCode TYPE##_copy(TYPE const *src, TYPE *dst) { \
  47. *dst = *src; \
  48. return UA_STATUSCODE_GOOD; \
  49. }
  50. /*****************/
  51. /* Builtin Types */
  52. /*****************/
  53. /* Boolean */
  54. UA_TYPE_DEFAULT(UA_Boolean)
  55. /* SByte */
  56. UA_TYPE_DEFAULT(UA_SByte)
  57. /* Byte */
  58. UA_TYPE_DEFAULT(UA_Byte)
  59. /* Int16 */
  60. UA_TYPE_DEFAULT(UA_Int16)
  61. /* UInt16 */
  62. UA_TYPE_DEFAULT(UA_UInt16)
  63. /* Int32 */
  64. UA_TYPE_DEFAULT(UA_Int32)
  65. /* UInt32 */
  66. UA_TYPE_DEFAULT(UA_UInt32)
  67. /* Int64 */
  68. UA_TYPE_DEFAULT(UA_Int64)
  69. /* UInt64 */
  70. UA_TYPE_DEFAULT(UA_UInt64)
  71. /* Float */
  72. UA_TYPE_DEFAULT(UA_Float)
  73. /* Double */
  74. UA_TYPE_DEFAULT(UA_Double)
  75. /* String */
  76. UA_TYPE_NEW_DEFAULT(UA_String)
  77. void UA_String_init(UA_String *p) {
  78. p->length = -1;
  79. p->data = UA_NULL;
  80. }
  81. UA_TYPE_DELETE_DEFAULT(UA_String)
  82. void UA_String_deleteMembers(UA_String *p) {
  83. UA_free(p->data);
  84. }
  85. UA_StatusCode UA_String_copy(UA_String const *src, UA_String *dst) {
  86. UA_String_init(dst);
  87. if(src->length > 0) {
  88. if(!(dst->data = UA_malloc((UA_UInt32)src->length)))
  89. return UA_STATUSCODE_BADOUTOFMEMORY;
  90. UA_memcpy((void *)dst->data, src->data, (UA_UInt32)src->length);
  91. }
  92. dst->length = src->length;
  93. return UA_STATUSCODE_GOOD;
  94. }
  95. /* The c-string needs to be null-terminated. the string cannot be smaller than zero. */
  96. UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
  97. UA_UInt32 length = (UA_UInt32) strlen(src);
  98. if(length == 0) {
  99. dst->length = 0;
  100. dst->data = UA_NULL;
  101. return UA_STATUSCODE_GOOD;
  102. }
  103. dst->data = UA_malloc(length);
  104. if(dst->data != UA_NULL) {
  105. UA_memcpy(dst->data, src, length);
  106. dst->length = (UA_Int32) (length & ~(1<<31)); // the highest bit is always zero to avoid overflows into negative values
  107. } else {
  108. dst->length = -1;
  109. return UA_STATUSCODE_BADOUTOFMEMORY;
  110. }
  111. return UA_STATUSCODE_GOOD;
  112. }
  113. #define UA_STRING_COPYPRINTF_BUFSIZE 1024
  114. UA_StatusCode UA_String_copyprintf(char const *fmt, UA_String *dst, ...) {
  115. char src[UA_STRING_COPYPRINTF_BUFSIZE];
  116. va_list ap;
  117. va_start(ap, dst);
  118. #if defined(__GNUC__) || defined(__clang__)
  119. #pragma GCC diagnostic push
  120. #pragma GCC diagnostic ignored "-Wformat-nonliteral"
  121. #endif
  122. // vsnprintf should only take a literal and no variable to be secure
  123. UA_Int32 len = vsnprintf(src, UA_STRING_COPYPRINTF_BUFSIZE, fmt, ap);
  124. #if defined(__GNUC__) || defined(__clang__)
  125. #pragma GCC diagnostic pop
  126. #endif
  127. va_end(ap);
  128. if(len < 0) // FIXME: old glibc 2.0 would return -1 when truncated
  129. return UA_STATUSCODE_BADINTERNALERROR;
  130. // since glibc 2.1 vsnprintf returns the len that would have resulted if buf were large enough
  131. len = ( len > UA_STRING_COPYPRINTF_BUFSIZE ? UA_STRING_COPYPRINTF_BUFSIZE : len );
  132. if(!(dst->data = UA_malloc((UA_UInt32)len)))
  133. return UA_STATUSCODE_BADOUTOFMEMORY;
  134. UA_memcpy((void *)dst->data, src, (UA_UInt32)len);
  135. dst->length = len;
  136. return UA_STATUSCODE_GOOD;
  137. }
  138. UA_Boolean UA_String_equal(const UA_String *string1, const UA_String *string2) {
  139. if(string1->length <= 0 && string2->length <= 0)
  140. return UA_TRUE;
  141. if(string1->length != string2->length)
  142. return UA_FALSE;
  143. // casts are needed to overcome signed warnings
  144. UA_Int32 is = strncmp((char const *)string1->data, (char const *)string2->data, (size_t)string1->length);
  145. return (is == 0) ? UA_TRUE : UA_FALSE;
  146. }
  147. /* DateTime */
  148. #define UNIX_EPOCH_BIAS_SEC 11644473600LL // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
  149. #define HUNDRED_NANOSEC_PER_USEC 10LL
  150. #define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
  151. #ifdef __MINGW32__
  152. #ifndef _TIMEZONE_DEFINED
  153. #define _TIMEZONE_DEFINED
  154. struct timezone {
  155. int tz_minuteswest;
  156. int tz_dsttime;
  157. };
  158. #endif
  159. #endif
  160. #ifdef _WIN32
  161. static const unsigned __int64 epoch = 116444736000000000;
  162. int gettimeofday(struct timeval *tp, struct timezone *tzp);
  163. int gettimeofday(struct timeval *tp, struct timezone *tzp) {
  164. FILETIME ft;
  165. SYSTEMTIME st;
  166. ULARGE_INTEGER ul;
  167. GetSystemTime(&st);
  168. SystemTimeToFileTime(&st, &ft);
  169. ul.LowPart = ft.dwLowDateTime;
  170. ul.HighPart = ft.dwHighDateTime;
  171. tp->tv_sec = (ul.QuadPart - epoch) / 10000000L;
  172. tp->tv_usec = st.wMilliseconds * 1000;
  173. return 0;
  174. }
  175. #endif
  176. UA_DateTime UA_DateTime_now() {
  177. UA_DateTime dateTime;
  178. struct timeval tv;
  179. gettimeofday(&tv, UA_NULL);
  180. dateTime = (tv.tv_sec + UNIX_EPOCH_BIAS_SEC)
  181. * HUNDRED_NANOSEC_PER_SEC + tv.tv_usec * HUNDRED_NANOSEC_PER_USEC;
  182. return dateTime;
  183. }
  184. UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime atime) {
  185. UA_DateTimeStruct dateTimeStruct;
  186. //calcualting the the milli-, micro- and nanoseconds
  187. dateTimeStruct.nanoSec = (UA_Int16)((atime % 10) * 100);
  188. dateTimeStruct.microSec = (UA_Int16)((atime % 10000) / 10);
  189. dateTimeStruct.milliSec = (UA_Int16)((atime % 10000000) / 10000);
  190. //calculating the unix time with #include <time.h>
  191. time_t secSinceUnixEpoch = (atime/10000000) - UNIX_EPOCH_BIAS_SEC;
  192. struct tm ts = *gmtime(&secSinceUnixEpoch);
  193. dateTimeStruct.sec = (UA_Int16)ts.tm_sec;
  194. dateTimeStruct.min = (UA_Int16)ts.tm_min;
  195. dateTimeStruct.hour = (UA_Int16)ts.tm_hour;
  196. dateTimeStruct.day = (UA_Int16)ts.tm_mday;
  197. dateTimeStruct.month = (UA_Int16)(ts.tm_mon + 1);
  198. dateTimeStruct.year = (UA_Int16)(ts.tm_year + 1900);
  199. return dateTimeStruct;
  200. }
  201. UA_StatusCode UA_DateTime_toString(UA_DateTime atime, UA_String *timeString) {
  202. // length of the string is 31 (incl. \0 at the end)
  203. if(!(timeString->data = UA_malloc(32)))
  204. return UA_STATUSCODE_BADOUTOFMEMORY;
  205. timeString->length = 31;
  206. UA_DateTimeStruct tSt = UA_DateTime_toStruct(atime);
  207. sprintf((char*)timeString->data, "%02d/%02d/%04d %02d:%02d:%02d.%03d.%03d.%03d", tSt.month, tSt.day, tSt.year,
  208. tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
  209. return UA_STATUSCODE_GOOD;
  210. }
  211. /* Guid */
  212. UA_TYPE_DELETEMEMBERS_NOACTION(UA_Guid)
  213. UA_TYPE_DELETE_DEFAULT(UA_Guid)
  214. UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
  215. if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
  216. return UA_TRUE;
  217. return UA_FALSE;
  218. }
  219. UA_Guid UA_Guid_random(UA_UInt32 *seed) {
  220. UA_Guid result;
  221. result.data1 = RAND(seed);
  222. UA_UInt32 r = RAND(seed);
  223. result.data2 = (UA_UInt16) r;
  224. result.data3 = (UA_UInt16) (r >> 16);
  225. r = RAND(seed);
  226. result.data4[0] = (UA_Byte)r;
  227. result.data4[1] = (UA_Byte)(r >> 4);
  228. result.data4[2] = (UA_Byte)(r >> 8);
  229. result.data4[3] = (UA_Byte)(r >> 12);
  230. r = RAND(seed);
  231. result.data4[4] = (UA_Byte)r;
  232. result.data4[5] = (UA_Byte)(r >> 4);
  233. result.data4[6] = (UA_Byte)(r >> 8);
  234. result.data4[7] = (UA_Byte)(r >> 12);
  235. return result;
  236. }
  237. void UA_Guid_init(UA_Guid *p) {
  238. p->data1 = 0;
  239. p->data2 = 0;
  240. p->data3 = 0;
  241. memset(p->data4, 0, sizeof(UA_Byte)*8);
  242. }
  243. UA_TYPE_NEW_DEFAULT(UA_Guid)
  244. UA_StatusCode UA_Guid_copy(UA_Guid const *src, UA_Guid *dst) {
  245. UA_memcpy((void *)dst, (const void *)src, sizeof(UA_Guid));
  246. return UA_STATUSCODE_GOOD;
  247. }
  248. /* ByteString */
  249. UA_StatusCode UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length) {
  250. if(length > 0) {
  251. if(!(p->data = UA_malloc((UA_UInt32)length)))
  252. return UA_STATUSCODE_BADOUTOFMEMORY;
  253. p->length = length;
  254. } else {
  255. p->data = UA_NULL;
  256. if(length == 0)
  257. p->length = 0;
  258. else
  259. p->length = -1;
  260. }
  261. return UA_STATUSCODE_GOOD;
  262. }
  263. /* XmlElement */
  264. /* NodeId */
  265. void UA_NodeId_init(UA_NodeId *p) {
  266. p->identifierType = UA_NODEIDTYPE_NUMERIC;
  267. p->namespaceIndex = 0;
  268. memset(&p->identifier, 0, sizeof(p->identifier));
  269. }
  270. UA_TYPE_NEW_DEFAULT(UA_NodeId)
  271. UA_StatusCode UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst) {
  272. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  273. switch(src->identifierType) {
  274. case UA_NODEIDTYPE_NUMERIC:
  275. *dst = *src;
  276. return UA_STATUSCODE_GOOD;
  277. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  278. retval |= UA_String_copy(&src->identifier.string, &dst->identifier.string);
  279. break;
  280. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  281. retval |= UA_Guid_copy(&src->identifier.guid, &dst->identifier.guid);
  282. break;
  283. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  284. retval |= UA_ByteString_copy(&src->identifier.byteString, &dst->identifier.byteString);
  285. break;
  286. default:
  287. UA_NodeId_init(dst);
  288. return UA_STATUSCODE_BADINTERNALERROR;
  289. }
  290. dst->namespaceIndex = src->namespaceIndex;
  291. dst->identifierType = src->identifierType;
  292. if(retval) {
  293. UA_NodeId_deleteMembers(dst);
  294. UA_NodeId_init(dst);
  295. }
  296. return retval;
  297. }
  298. static UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id) {
  299. return id ->namespaceIndex == 0 && 1 <= id ->identifier.numeric &&
  300. id ->identifier.numeric <= 25;
  301. }
  302. UA_TYPE_DELETE_DEFAULT(UA_NodeId)
  303. void UA_NodeId_deleteMembers(UA_NodeId *p) {
  304. switch(p->identifierType) {
  305. case UA_NODEIDTYPE_NUMERIC:
  306. // nothing to do
  307. break;
  308. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  309. UA_String_deleteMembers(&p->identifier.string);
  310. break;
  311. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  312. UA_Guid_deleteMembers(&p->identifier.guid);
  313. break;
  314. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  315. UA_ByteString_deleteMembers(&p->identifier.byteString);
  316. break;
  317. }
  318. }
  319. UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
  320. if(n1->namespaceIndex != n2->namespaceIndex || n1->identifierType!=n2->identifierType)
  321. return UA_FALSE;
  322. switch(n1->identifierType) {
  323. case UA_NODEIDTYPE_NUMERIC:
  324. if(n1->identifier.numeric == n2->identifier.numeric)
  325. return UA_TRUE;
  326. else
  327. return UA_FALSE;
  328. case UA_NODEIDTYPE_STRING:
  329. return UA_String_equal(&n1->identifier.string, &n2->identifier.string);
  330. case UA_NODEIDTYPE_GUID:
  331. return UA_Guid_equal(&n1->identifier.guid, &n2->identifier.guid);
  332. case UA_NODEIDTYPE_BYTESTRING:
  333. return UA_ByteString_equal(&n1->identifier.byteString, &n2->identifier.byteString);
  334. }
  335. return UA_FALSE;
  336. }
  337. UA_Boolean UA_NodeId_isNull(const UA_NodeId *p) {
  338. switch(p->identifierType) {
  339. case UA_NODEIDTYPE_NUMERIC:
  340. if(p->namespaceIndex != 0 || p->identifier.numeric != 0)
  341. return UA_FALSE;
  342. break;
  343. case UA_NODEIDTYPE_STRING:
  344. if(p->namespaceIndex != 0 || p->identifier.string.length != 0)
  345. return UA_FALSE;
  346. break;
  347. case UA_NODEIDTYPE_GUID:
  348. if(p->namespaceIndex != 0 ||
  349. memcmp(&p->identifier.guid, (char[sizeof(UA_Guid)]) { 0 }, sizeof(UA_Guid)) != 0)
  350. return UA_FALSE;
  351. break;
  352. case UA_NODEIDTYPE_BYTESTRING:
  353. if(p->namespaceIndex != 0 || p->identifier.byteString.length != 0)
  354. return UA_FALSE;
  355. break;
  356. default:
  357. return UA_FALSE;
  358. }
  359. return UA_TRUE;
  360. }
  361. /* ExpandedNodeId */
  362. UA_TYPE_DELETE_DEFAULT(UA_ExpandedNodeId)
  363. void UA_ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p) {
  364. UA_NodeId_deleteMembers(&p->nodeId);
  365. UA_String_deleteMembers(&p->namespaceUri);
  366. }
  367. void UA_ExpandedNodeId_init(UA_ExpandedNodeId *p) {
  368. UA_NodeId_init(&p->nodeId);
  369. UA_String_init(&p->namespaceUri);
  370. p->serverIndex = 0;
  371. }
  372. UA_TYPE_NEW_DEFAULT(UA_ExpandedNodeId)
  373. UA_StatusCode UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst) {
  374. UA_StatusCode retval = UA_NodeId_copy(&src->nodeId, &dst->nodeId);
  375. retval |= UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
  376. dst->serverIndex = src->serverIndex;
  377. if(retval) {
  378. UA_ExpandedNodeId_deleteMembers(dst);
  379. UA_ExpandedNodeId_init(dst);
  380. }
  381. return retval;
  382. }
  383. UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p) {
  384. return UA_NodeId_isNull(&p->nodeId);
  385. }
  386. /* StatusCode */
  387. /* QualifiedName */
  388. UA_TYPE_DELETE_DEFAULT(UA_QualifiedName)
  389. void UA_QualifiedName_deleteMembers(UA_QualifiedName *p) {
  390. UA_String_deleteMembers(&p->name);
  391. }
  392. void UA_QualifiedName_init(UA_QualifiedName *p) {
  393. UA_String_init(&p->name);
  394. p->namespaceIndex = 0;
  395. }
  396. UA_TYPE_NEW_DEFAULT(UA_QualifiedName)
  397. UA_StatusCode UA_QualifiedName_copy(UA_QualifiedName const *src, UA_QualifiedName *dst) {
  398. UA_StatusCode retval = UA_String_copy(&src->name, &dst->name);
  399. dst->namespaceIndex = src->namespaceIndex;
  400. if(retval) {
  401. UA_QualifiedName_deleteMembers(dst);
  402. UA_QualifiedName_init(dst);
  403. }
  404. return retval;
  405. }
  406. UA_StatusCode UA_QualifiedName_copycstring(char const *src, UA_QualifiedName *dst) {
  407. dst->namespaceIndex = 0;
  408. return UA_String_copycstring(src, &dst->name);
  409. }
  410. /* LocalizedText */
  411. UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
  412. void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
  413. UA_String_deleteMembers(&p->locale);
  414. UA_String_deleteMembers(&p->text);
  415. }
  416. void UA_LocalizedText_init(UA_LocalizedText *p) {
  417. UA_String_init(&p->locale);
  418. UA_String_init(&p->text);
  419. }
  420. UA_TYPE_NEW_DEFAULT(UA_LocalizedText)
  421. UA_StatusCode UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst) {
  422. UA_StatusCode retval = UA_String_copycstring("", &dst->locale);
  423. retval |= UA_String_copycstring(src, &dst->text);
  424. if(retval) {
  425. UA_LocalizedText_deleteMembers(dst);
  426. UA_LocalizedText_init(dst);
  427. }
  428. return retval;
  429. }
  430. UA_StatusCode UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst) {
  431. UA_StatusCode retval = UA_String_copy(&src->locale, &dst->locale);
  432. retval |= UA_String_copy(&src->text, &dst->text);
  433. if(retval) {
  434. UA_LocalizedText_deleteMembers(dst);
  435. UA_LocalizedText_init(dst);
  436. }
  437. return retval;
  438. }
  439. /* ExtensionObject */
  440. UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
  441. void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
  442. UA_NodeId_deleteMembers(&p->typeId);
  443. UA_ByteString_deleteMembers(&p->body);
  444. }
  445. void UA_ExtensionObject_init(UA_ExtensionObject *p) {
  446. UA_NodeId_init(&p->typeId);
  447. p->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED;
  448. UA_ByteString_init(&p->body);
  449. }
  450. UA_TYPE_NEW_DEFAULT(UA_ExtensionObject)
  451. UA_StatusCode UA_ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst) {
  452. UA_StatusCode retval = UA_ByteString_copy(&src->body, &dst->body);
  453. retval |= UA_NodeId_copy(&src->typeId, &dst->typeId);
  454. dst->encoding = src->encoding;
  455. if(retval) {
  456. UA_ExtensionObject_deleteMembers(dst);
  457. UA_ExtensionObject_init(dst);
  458. }
  459. return retval;
  460. }
  461. /* DataValue */
  462. UA_TYPE_DELETE_DEFAULT(UA_DataValue)
  463. void UA_DataValue_deleteMembers(UA_DataValue *p) {
  464. UA_Variant_deleteMembers(&p->value);
  465. }
  466. void UA_DataValue_init(UA_DataValue *p) {
  467. *((UA_Byte*)p) = 0; // zero out the bitfield
  468. p->serverPicoseconds = 0;
  469. UA_DateTime_init(&p->serverTimestamp);
  470. p->sourcePicoseconds = 0;
  471. UA_DateTime_init(&p->sourceTimestamp);
  472. UA_StatusCode_init(&p->status);
  473. UA_Variant_init(&p->value);
  474. }
  475. UA_TYPE_NEW_DEFAULT(UA_DataValue)
  476. UA_StatusCode UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst) {
  477. UA_DataValue_init(dst);
  478. *((UA_Byte*)dst) = *((const UA_Byte*)src); // the bitfield
  479. UA_StatusCode retval = UA_DateTime_copy(&src->serverTimestamp, &dst->serverTimestamp);
  480. retval |= UA_DateTime_copy(&src->sourceTimestamp, &dst->sourceTimestamp);
  481. retval |= UA_Variant_copy(&src->value, &dst->value);
  482. dst->serverPicoseconds = src->serverPicoseconds;
  483. dst->sourcePicoseconds = src->sourcePicoseconds;
  484. dst->status = src->status;
  485. if(retval) {
  486. UA_DataValue_deleteMembers(dst);
  487. UA_DataValue_init(dst);
  488. }
  489. return retval;
  490. }
  491. /* Variant */
  492. UA_TYPE_NEW_DEFAULT(UA_Variant)
  493. void UA_Variant_init(UA_Variant *p) {
  494. p->storageType = UA_VARIANT_DATA;
  495. p->arrayLength = -1;
  496. p->dataPtr = UA_NULL;
  497. p->arrayDimensions = UA_NULL;
  498. p->arrayDimensionsSize = -1;
  499. p->type = UA_NULL;
  500. }
  501. UA_TYPE_DELETE_DEFAULT(UA_Variant)
  502. void UA_Variant_deleteMembers(UA_Variant *p) {
  503. if(p->storageType == UA_VARIANT_DATA) {
  504. if(p->dataPtr) {
  505. UA_Array_delete(p->dataPtr, p->type, p->arrayLength);
  506. p->dataPtr = UA_NULL;
  507. p->arrayLength = -1;
  508. }
  509. if(p->arrayDimensions) {
  510. UA_free(p->arrayDimensions);
  511. p->arrayDimensions = UA_NULL;
  512. }
  513. }
  514. }
  515. UA_StatusCode UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
  516. UA_Variant_init(dst);
  517. dst->type = src->type;
  518. dst->storageType = UA_VARIANT_DATA;
  519. UA_StatusCode retval = UA_Array_copy(src->dataPtr, &dst->dataPtr, src->type, src->arrayLength);
  520. if(retval != UA_STATUSCODE_GOOD) {
  521. UA_Variant_deleteMembers(dst);
  522. UA_Variant_init(dst);
  523. return retval;
  524. }
  525. dst->arrayLength = src->arrayLength;
  526. if(src->arrayDimensions) {
  527. retval |= UA_Array_copy(src->arrayDimensions, (void **)&dst->arrayDimensions,
  528. &UA_TYPES[UA_TYPES_INT32], src->arrayDimensionsSize);
  529. if(retval != UA_STATUSCODE_GOOD) {
  530. UA_Variant_deleteMembers(dst);
  531. UA_Variant_init(dst);
  532. }
  533. }
  534. dst->arrayDimensionsSize = src->arrayDimensionsSize;
  535. return retval;
  536. }
  537. UA_StatusCode UA_Variant_setValue(UA_Variant *v, void *p, const UA_DataType *type) {
  538. return UA_Variant_setArray(v, p, 1, type);
  539. }
  540. UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const void *p, const UA_DataType *type) {
  541. void *new = UA_malloc(type->memSize);
  542. if(!new)
  543. return UA_STATUSCODE_BADOUTOFMEMORY;
  544. UA_StatusCode retval = UA_copy(p, new, type);
  545. if(retval != UA_STATUSCODE_GOOD) {
  546. UA_delete(new, type);
  547. return retval;
  548. }
  549. return UA_Variant_setArray(v, new, 1, type);
  550. }
  551. UA_StatusCode UA_Variant_setArray(UA_Variant *v, void *array, UA_Int32 noElements,
  552. const UA_DataType *type) {
  553. v->type = type;
  554. v->arrayLength = noElements;
  555. v->dataPtr = array;
  556. return UA_STATUSCODE_GOOD;
  557. }
  558. UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const void *array, UA_Int32 noElements,
  559. const UA_DataType *type) {
  560. void *new;
  561. UA_StatusCode retval = UA_Array_copy(array, &new, type, noElements);
  562. if(retval != UA_STATUSCODE_GOOD)
  563. return retval;
  564. return UA_Variant_setArray(v, new, noElements, type);
  565. }
  566. /* DiagnosticInfo */
  567. UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
  568. void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
  569. UA_String_deleteMembers(&p->additionalInfo);
  570. if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
  571. UA_DiagnosticInfo_delete(p->innerDiagnosticInfo);
  572. p->innerDiagnosticInfo = UA_NULL;
  573. }
  574. }
  575. UA_TYPE_NEW_DEFAULT(UA_DiagnosticInfo)
  576. void UA_DiagnosticInfo_init(UA_DiagnosticInfo *p) {
  577. p->hasSymbolicId = UA_FALSE;
  578. p->hasNamespaceUri = UA_FALSE;
  579. p->hasLocalizedText = UA_FALSE;
  580. p->hasLocale = UA_FALSE;
  581. p->hasAdditionalInfo = UA_FALSE;
  582. p->hasInnerStatusCode = UA_FALSE;
  583. p->hasInnerDiagnosticInfo = UA_FALSE;
  584. p->symbolicId = 0;
  585. p->namespaceUri = 0;
  586. p->localizedText = 0;
  587. p->locale = 0;
  588. UA_String_init(&p->additionalInfo);
  589. p->innerDiagnosticInfo = UA_NULL;
  590. UA_StatusCode_init(&p->innerStatusCode);
  591. }
  592. UA_StatusCode UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst) {
  593. UA_DiagnosticInfo_init(dst);
  594. dst->hasSymbolicId = src->hasSymbolicId;
  595. dst->hasNamespaceUri = src->hasNamespaceUri;
  596. dst->hasLocalizedText = src->hasLocalizedText;
  597. dst->hasLocale = src->hasLocale;
  598. dst->hasAdditionalInfo = src->hasAdditionalInfo;
  599. dst->hasInnerStatusCode = src->hasInnerStatusCode;
  600. dst->symbolicId = src->symbolicId;
  601. dst->namespaceUri = src->namespaceUri;
  602. dst->localizedText = src->localizedText;
  603. dst->locale = src->locale;
  604. dst->innerStatusCode = src->innerStatusCode;
  605. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  606. if(src->hasAdditionalInfo)
  607. retval = UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
  608. if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
  609. if((dst->innerDiagnosticInfo = UA_malloc(sizeof(UA_DiagnosticInfo)))) {
  610. retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
  611. dst->hasInnerDiagnosticInfo = src->hasInnerDiagnosticInfo;
  612. }
  613. else
  614. retval |= UA_STATUSCODE_BADOUTOFMEMORY;
  615. }
  616. if(retval) {
  617. UA_DiagnosticInfo_deleteMembers(dst);
  618. UA_DiagnosticInfo_init(dst);
  619. }
  620. return retval;
  621. }
  622. /*******************/
  623. /* Structure Types */
  624. /*******************/
  625. void UA_init(void *p, const UA_DataType *dataType) {
  626. /* Do not check if the index is a builtin-type here. Builtins will be called
  627. with their very own _init functions normally. In the off case, that the
  628. generic function is called with the index of a builtin, their layout
  629. contains a single member of the builtin type, that will be inited in the
  630. for loop. */
  631. uintptr_t ptr = (uintptr_t)p;
  632. UA_Byte membersSize = dataType->membersSize;
  633. for(size_t i=0;i<membersSize; i++) {
  634. const UA_DataTypeMember *member = &dataType->members[i];
  635. if(member->isArray) {
  636. /* Padding contains bit-magic to split into padding before and after
  637. the length integer */
  638. ptr += (member->padding >> 3);
  639. *((UA_Int32*)ptr) = -1;
  640. ptr += sizeof(UA_Int32) + (member->padding & 0x07);
  641. *((void**)ptr) = UA_NULL;
  642. ptr += sizeof(void*);
  643. continue;
  644. }
  645. ptr += member->padding;
  646. if(!member->namespaceZero) {
  647. // pointer arithmetic
  648. const UA_DataType *memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  649. UA_init((void*)ptr, memberType);
  650. ptr += memberType->memSize;
  651. continue;
  652. }
  653. switch(member->memberTypeIndex) {
  654. case UA_TYPES_BOOLEAN:
  655. case UA_TYPES_SBYTE:
  656. case UA_TYPES_BYTE:
  657. *(UA_Byte*)ptr = 0;
  658. break;
  659. case UA_TYPES_INT16:
  660. case UA_TYPES_UINT16:
  661. *(UA_Int16*)ptr = 0;
  662. break;
  663. case UA_TYPES_INT32:
  664. case UA_TYPES_UINT32:
  665. case UA_TYPES_STATUSCODE:
  666. case UA_TYPES_FLOAT:
  667. *(UA_Int32*)ptr = 0;
  668. break;
  669. case UA_TYPES_INT64:
  670. case UA_TYPES_UINT64:
  671. case UA_TYPES_DOUBLE:
  672. case UA_TYPES_DATETIME:
  673. *(UA_Int64*)ptr = 0;
  674. break;
  675. case UA_TYPES_GUID:
  676. UA_Guid_init((UA_Guid*)ptr);
  677. break;
  678. case UA_TYPES_NODEID:
  679. UA_NodeId_init((UA_NodeId*)ptr);
  680. break;
  681. case UA_TYPES_EXPANDEDNODEID:
  682. UA_ExpandedNodeId_init((UA_ExpandedNodeId*)ptr);
  683. break;
  684. case UA_TYPES_QUALIFIEDNAME:
  685. UA_QualifiedName_init((UA_QualifiedName*)ptr);
  686. break;
  687. case UA_TYPES_LOCALIZEDTEXT:
  688. UA_LocalizedText_init((UA_LocalizedText*)ptr);
  689. break;
  690. case UA_TYPES_EXTENSIONOBJECT:
  691. UA_ExtensionObject_init((UA_ExtensionObject*)ptr);
  692. break;
  693. case UA_TYPES_DATAVALUE:
  694. UA_DataValue_init((UA_DataValue*)ptr);
  695. break;
  696. case UA_TYPES_VARIANT:
  697. UA_Variant_init((UA_Variant*)ptr);
  698. break;
  699. case UA_TYPES_DIAGNOSTICINFO:
  700. UA_DiagnosticInfo_init((UA_DiagnosticInfo*)ptr);
  701. break;
  702. case UA_TYPES_STRING:
  703. case UA_TYPES_BYTESTRING:
  704. case UA_TYPES_XMLELEMENT:
  705. UA_String_init((UA_String*)ptr);
  706. break;
  707. default:
  708. UA_init((void*)ptr, &UA_TYPES[member->memberTypeIndex]);
  709. }
  710. ptr += UA_TYPES[member->memberTypeIndex].memSize;
  711. }
  712. }
  713. void * UA_new(const UA_DataType *dataType) {
  714. void *p = UA_malloc(dataType->memSize);
  715. if(p)
  716. UA_init(p, dataType);
  717. return p;
  718. }
  719. UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *dataType) {
  720. if(dataType->fixedSize) {
  721. memcpy(dst, src, dataType->memSize);
  722. return UA_STATUSCODE_GOOD;
  723. }
  724. UA_init(dst, dataType);
  725. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  726. uintptr_t ptrs = (uintptr_t)src;
  727. uintptr_t ptrd = (uintptr_t)dst;
  728. UA_Byte membersSize = dataType->membersSize;
  729. for(size_t i=0;i<membersSize; i++) {
  730. const UA_DataTypeMember *member = &dataType->members[i];
  731. const UA_DataType *memberType;
  732. if(member->namespaceZero)
  733. memberType = &UA_TYPES[member->memberTypeIndex];
  734. else
  735. memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  736. if(member->isArray) {
  737. ptrs += (member->padding >> 3);
  738. ptrd += (member->padding >> 3);
  739. UA_Int32 *dstNoElements = (UA_Int32*)ptrd;
  740. const UA_Int32 noElements = *((const UA_Int32*)ptrs);
  741. ptrs += sizeof(UA_Int32) + (member->padding & 0x07);
  742. ptrd += sizeof(UA_Int32) + (member->padding & 0x07);
  743. retval = UA_Array_copy(*(void* const*)ptrs, (void**)ptrd, memberType, noElements);
  744. if(retval != UA_STATUSCODE_GOOD) {
  745. UA_deleteMembers(dst, dataType);
  746. UA_init(dst, dataType);
  747. return retval;
  748. }
  749. *dstNoElements = noElements;
  750. ptrs += sizeof(void*);
  751. ptrd += sizeof(void*);
  752. continue;
  753. }
  754. ptrs += member->padding;
  755. ptrd += member->padding;
  756. if(!member->namespaceZero) {
  757. retval = UA_copy((const void*)ptrs, (void*)ptrd, memberType);
  758. if(retval != UA_STATUSCODE_GOOD) {
  759. UA_deleteMembers(dst, dataType);
  760. UA_init(dst, dataType);
  761. return retval;
  762. }
  763. ptrs += memberType->memSize;
  764. ptrd += memberType->memSize;
  765. continue;
  766. }
  767. switch(member->memberTypeIndex) {
  768. case UA_TYPES_BOOLEAN:
  769. case UA_TYPES_SBYTE:
  770. case UA_TYPES_BYTE:
  771. *((UA_Byte*)ptrd) = *((const UA_Byte*)ptrs);
  772. break;
  773. case UA_TYPES_INT16:
  774. case UA_TYPES_UINT16:
  775. *((UA_Int16*)ptrd) = *((const UA_Byte*)ptrs);
  776. break;
  777. case UA_TYPES_INT32:
  778. case UA_TYPES_UINT32:
  779. case UA_TYPES_STATUSCODE:
  780. case UA_TYPES_FLOAT:
  781. *((UA_Int32*)ptrd) = *((const UA_Int32*)ptrs);
  782. break;
  783. case UA_TYPES_INT64:
  784. case UA_TYPES_UINT64:
  785. case UA_TYPES_DOUBLE:
  786. case UA_TYPES_DATETIME:
  787. *((UA_Int64*)ptrd) = *((const UA_Int64*)ptrs);
  788. break;
  789. case UA_TYPES_GUID:
  790. *((UA_Guid*)ptrd) = *((const UA_Guid*)ptrs);
  791. break;
  792. case UA_TYPES_NODEID:
  793. retval |= UA_NodeId_copy((const UA_NodeId*)ptrs, (UA_NodeId*)ptrd);
  794. break;
  795. case UA_TYPES_EXPANDEDNODEID:
  796. retval |= UA_ExpandedNodeId_copy((const UA_ExpandedNodeId*)ptrs, (UA_ExpandedNodeId*)ptrd);
  797. break;
  798. case UA_TYPES_QUALIFIEDNAME:
  799. retval |= UA_QualifiedName_copy((const UA_QualifiedName*)ptrs, (UA_QualifiedName*)ptrd);
  800. break;
  801. case UA_TYPES_LOCALIZEDTEXT:
  802. retval |= UA_LocalizedText_copy((const UA_LocalizedText*)ptrs, (UA_LocalizedText*)ptrd);
  803. break;
  804. case UA_TYPES_EXTENSIONOBJECT:
  805. retval |= UA_ExtensionObject_copy((const UA_ExtensionObject*)ptrs, (UA_ExtensionObject*)ptrd);
  806. break;
  807. case UA_TYPES_DATAVALUE:
  808. retval |= UA_DataValue_copy((const UA_DataValue*)ptrs, (UA_DataValue*)ptrd);
  809. break;
  810. case UA_TYPES_VARIANT:
  811. retval |= UA_Variant_copy((const UA_Variant*)ptrs, (UA_Variant*)ptrd);
  812. break;
  813. case UA_TYPES_DIAGNOSTICINFO:
  814. retval |= UA_DiagnosticInfo_copy((const UA_DiagnosticInfo*)ptrs, (UA_DiagnosticInfo*)ptrd);
  815. break;
  816. case UA_TYPES_STRING:
  817. case UA_TYPES_BYTESTRING:
  818. case UA_TYPES_XMLELEMENT:
  819. retval |= UA_String_copy((const UA_String*)ptrs, (UA_String*)ptrd);
  820. break;
  821. default:
  822. retval |= UA_copy((const void *)ptrs, (void*)ptrd, memberType);
  823. }
  824. ptrs += memberType->memSize;
  825. ptrd += memberType->memSize;
  826. }
  827. if(retval != UA_STATUSCODE_GOOD) {
  828. UA_deleteMembers(dst, dataType);
  829. UA_init(dst, dataType);
  830. }
  831. return retval;
  832. }
  833. void UA_deleteMembers(void *p, const UA_DataType *dataType) {
  834. uintptr_t ptr = (uintptr_t)p;
  835. if(dataType->fixedSize)
  836. return;
  837. UA_Byte membersSize = dataType->membersSize;
  838. for(size_t i=0;i<membersSize; i++) {
  839. const UA_DataTypeMember *member = &dataType->members[i];
  840. const UA_DataType *memberType;
  841. if(member->namespaceZero)
  842. memberType = &UA_TYPES[member->memberTypeIndex];
  843. else
  844. memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  845. if(member->isArray) {
  846. ptr += (member->padding >> 3);
  847. UA_Int32 noElements = *((UA_Int32*)ptr);
  848. ptr += sizeof(UA_Int32) + (member->padding & 0x07);
  849. UA_Array_delete(*(void**)ptr, memberType, noElements);
  850. ptr += sizeof(void*);
  851. continue;
  852. }
  853. ptr += member->padding;
  854. if(!member->namespaceZero) {
  855. UA_deleteMembers((void*)ptr, memberType);
  856. ptr += memberType->memSize;
  857. continue;
  858. }
  859. switch(member->memberTypeIndex) {
  860. // the following types have a fixed size.
  861. /* UA_BOOLEAN, UA_SBYTE, UA_BYTE, UA_INT16, UA_UINT16, UA_INT32, UA_UINT32, */
  862. /* UA_STATUSCODE, UA_FLOAT, UA_INT64, UA_UINT64, UA_DOUBLE, UA_DATETIME, UA_GUID */
  863. case UA_TYPES_NODEID:
  864. UA_NodeId_deleteMembers((UA_NodeId*)ptr);
  865. break;
  866. case UA_TYPES_EXPANDEDNODEID:
  867. UA_ExpandedNodeId_deleteMembers((UA_ExpandedNodeId*)ptr);
  868. break;
  869. case UA_TYPES_QUALIFIEDNAME:
  870. UA_QualifiedName_deleteMembers((UA_QualifiedName*)ptr);
  871. break;
  872. case UA_TYPES_LOCALIZEDTEXT:
  873. UA_LocalizedText_deleteMembers((UA_LocalizedText*)ptr);
  874. break;
  875. case UA_TYPES_EXTENSIONOBJECT:
  876. UA_ExtensionObject_deleteMembers((UA_ExtensionObject*)ptr);
  877. break;
  878. case UA_TYPES_DATAVALUE:
  879. UA_DataValue_deleteMembers((UA_DataValue*)ptr);
  880. break;
  881. case UA_TYPES_VARIANT:
  882. UA_Variant_deleteMembers((UA_Variant*)ptr);
  883. break;
  884. case UA_TYPES_DIAGNOSTICINFO:
  885. UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
  886. break;
  887. case UA_TYPES_STRING:
  888. case UA_TYPES_BYTESTRING:
  889. case UA_TYPES_XMLELEMENT:
  890. UA_String_deleteMembers((UA_String*)ptr);
  891. break;
  892. default:
  893. UA_deleteMembers((void*)ptr, memberType);
  894. }
  895. ptr += memberType->memSize;
  896. }
  897. }
  898. void UA_delete(void *p, const UA_DataType *dataType) {
  899. UA_deleteMembers(p, dataType);
  900. UA_free(p);
  901. }
  902. /******************/
  903. /* Array Handling */
  904. /******************/
  905. void* UA_Array_new(const UA_DataType *dataType, UA_Int32 noElements) {
  906. if(noElements <= 0)
  907. return UA_NULL;
  908. if((UA_Int32)dataType->memSize * noElements < 0 || dataType->memSize * noElements > MAX_ARRAY_SIZE )
  909. return UA_NULL;
  910. void *p = malloc(dataType->memSize * (size_t)noElements);
  911. if(!p || dataType->fixedSize) // datatypes of fixed size are not initialized.
  912. return p;
  913. uintptr_t ptr = (uintptr_t)p;
  914. for(int i = 0; i<noElements; i++) {
  915. UA_init((void*)ptr, dataType);
  916. ptr += dataType->memSize;
  917. }
  918. return p;
  919. }
  920. UA_StatusCode UA_Array_copy(const void *src, void **dst, const UA_DataType *dataType, UA_Int32 noElements) {
  921. if(noElements <= 0) {
  922. *dst = UA_NULL;
  923. return UA_STATUSCODE_GOOD;
  924. }
  925. if(!(*dst = UA_malloc((size_t)noElements * dataType->memSize)))
  926. return UA_STATUSCODE_BADOUTOFMEMORY;
  927. if(dataType->fixedSize) {
  928. memcpy(*dst, src, dataType->memSize * (size_t)noElements);
  929. return UA_STATUSCODE_GOOD;
  930. }
  931. uintptr_t ptrs = (uintptr_t)src;
  932. uintptr_t ptrd = (uintptr_t)*dst;
  933. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  934. for(int i=0;i<noElements; i++) {
  935. retval = UA_copy((void*)ptrs, (void*)ptrd, dataType);
  936. ptrs += dataType->memSize;
  937. ptrd += dataType->memSize;
  938. }
  939. if(retval != UA_STATUSCODE_GOOD)
  940. UA_Array_delete(*dst, dataType, noElements);
  941. return retval;
  942. }
  943. void UA_Array_delete(void *p, const UA_DataType *dataType, UA_Int32 noElements) {
  944. if(noElements <= 0 || !p)
  945. return;
  946. if(!dataType->fixedSize) {
  947. uintptr_t ptr = (uintptr_t)p;
  948. for(UA_Int32 i = 0; i<noElements; i++) {
  949. UA_deleteMembers((void*)ptr, dataType);
  950. ptr += dataType->memSize;
  951. }
  952. }
  953. UA_free(p);
  954. }