ua_types.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  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, "%2d/%2d/%4d %2d:%2d:%2d.%3d.%3d.%3d", 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)
  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("en", &dst->locale); // TODO: Are language codes upper case?
  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->storage.data.arrayLength = -1; // no element, p->data == UA_NULL
  496. p->storage.data.dataPtr = UA_NULL;
  497. p->storage.data.arrayDimensions = UA_NULL;
  498. p->storage.data.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->storage.data.dataPtr) {
  505. UA_Array_delete(p->storage.data.dataPtr, p->type, p->storage.data.arrayLength);
  506. p->storage.data.dataPtr = UA_NULL;
  507. p->storage.data.arrayLength = 0;
  508. }
  509. if(p->storage.data.arrayDimensions) {
  510. UA_free(p->storage.data.arrayDimensions);
  511. p->storage.data.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. if(src->storageType == UA_VARIANT_DATASOURCE) {
  519. dst->storageType = UA_VARIANT_DATASOURCE;
  520. dst->storage = src->storage;
  521. return UA_STATUSCODE_GOOD;
  522. }
  523. UA_VariantData *dstdata = &dst->storage.data;
  524. const UA_VariantData *srcdata = &src->storage.data;
  525. dst->storageType = UA_VARIANT_DATA;
  526. UA_StatusCode retval = UA_Array_copy(srcdata->dataPtr, &dstdata->dataPtr, src->type, srcdata->arrayLength);
  527. if(retval != UA_STATUSCODE_GOOD) {
  528. UA_Variant_deleteMembers(dst);
  529. UA_Variant_init(dst);
  530. return retval;
  531. }
  532. dstdata->arrayLength = srcdata->arrayLength;
  533. if(srcdata->arrayDimensions) {
  534. retval |= UA_Array_copy(srcdata->arrayDimensions, (void **)&dstdata->arrayDimensions, &UA_TYPES[UA_TYPES_INT32],
  535. srcdata->arrayDimensionsSize);
  536. if(retval != UA_STATUSCODE_GOOD) {
  537. UA_Variant_deleteMembers(dst);
  538. UA_Variant_init(dst);
  539. }
  540. }
  541. dstdata->arrayDimensionsSize = srcdata->arrayDimensionsSize;
  542. return retval;
  543. }
  544. UA_StatusCode UA_Variant_setValue(UA_Variant *v, void *p, UA_UInt16 typeIndex) {
  545. return UA_Variant_setArray(v, p, 1, typeIndex);
  546. }
  547. UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const void *p, UA_UInt16 typeIndex) {
  548. if(typeIndex >= UA_TYPES_COUNT)
  549. return UA_STATUSCODE_BADINTERNALERROR;
  550. const UA_DataType *type = &UA_TYPES[typeIndex];
  551. void *new = UA_malloc(type->memSize);
  552. if(!new)
  553. return UA_STATUSCODE_BADOUTOFMEMORY;
  554. UA_StatusCode retval = UA_copy(p, new, &UA_TYPES[typeIndex]);
  555. if(retval != UA_STATUSCODE_GOOD)
  556. return retval;
  557. return UA_Variant_setArray(v, new, 1, typeIndex);
  558. }
  559. UA_StatusCode UA_Variant_setArray(UA_Variant *v, void *array, UA_Int32 noElements,
  560. UA_UInt16 typeIndex) {
  561. if(typeIndex >= UA_TYPES_COUNT)
  562. return UA_STATUSCODE_BADINTERNALERROR;
  563. v->type = &UA_TYPES[typeIndex];
  564. v->storage.data.arrayLength = noElements;
  565. v->storage.data.dataPtr = array;
  566. return UA_STATUSCODE_GOOD;
  567. }
  568. UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const void *array, UA_Int32 noElements,
  569. UA_UInt16 typeIndex) {
  570. if(typeIndex >= UA_TYPES_COUNT)
  571. return UA_STATUSCODE_BADINTERNALERROR;
  572. void *new;
  573. UA_StatusCode retval = UA_Array_copy(array, &new, &UA_TYPES[typeIndex], noElements);
  574. if(retval != UA_STATUSCODE_GOOD)
  575. return retval;
  576. return UA_Variant_setArray(v, new, noElements, typeIndex);
  577. }
  578. /* DiagnosticInfo */
  579. UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
  580. void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
  581. UA_String_deleteMembers(&p->additionalInfo);
  582. if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
  583. UA_DiagnosticInfo_delete(p->innerDiagnosticInfo);
  584. p->innerDiagnosticInfo = UA_NULL;
  585. }
  586. }
  587. UA_TYPE_NEW_DEFAULT(UA_DiagnosticInfo)
  588. void UA_DiagnosticInfo_init(UA_DiagnosticInfo *p) {
  589. *(UA_Byte*)p = 0;
  590. p->symbolicId = 0;
  591. p->namespaceUri = 0;
  592. p->localizedText = 0;
  593. p->locale = 0;
  594. UA_String_init(&p->additionalInfo);
  595. p->innerDiagnosticInfo = UA_NULL;
  596. UA_StatusCode_init(&p->innerStatusCode);
  597. }
  598. UA_StatusCode UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst) {
  599. UA_DiagnosticInfo_init(dst);
  600. *(UA_Byte*)dst = *(const UA_Byte*)src; // bitfields
  601. UA_StatusCode retval = UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
  602. retval |= UA_StatusCode_copy(&src->innerStatusCode, &dst->innerStatusCode);
  603. if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
  604. if((dst->innerDiagnosticInfo = UA_malloc(sizeof(UA_DiagnosticInfo))))
  605. retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
  606. else
  607. retval |= UA_STATUSCODE_BADOUTOFMEMORY;
  608. }
  609. dst->locale = src->locale;
  610. dst->localizedText = src->localizedText;
  611. dst->namespaceUri = src->namespaceUri;
  612. dst->symbolicId = src->symbolicId;
  613. if(retval) {
  614. UA_DiagnosticInfo_deleteMembers(dst);
  615. UA_DiagnosticInfo_init(dst);
  616. }
  617. return retval;
  618. }
  619. /*******************/
  620. /* Structure Types */
  621. /*******************/
  622. void UA_init(void *p, const UA_DataType *dataType) {
  623. /* Do not check if the index is a builtin-type here. Builtins will be called
  624. with their very own _init functions normally. In the off case, that the
  625. generic function is called with the index of a builtin, their layout
  626. contains a single member of the builtin type, that will be inited in the
  627. for loop. */
  628. uintptr_t ptr = (uintptr_t)p;
  629. UA_Byte membersSize = dataType->membersSize;
  630. for(size_t i=0;i<membersSize; i++) {
  631. const UA_DataTypeMember *member = &dataType->members[i];
  632. if(member->isArray) {
  633. /* Padding contains bit-magic to split into padding before and after
  634. the length integer */
  635. ptr += (member->padding >> 3);
  636. *((UA_Int32*)ptr) = -1;
  637. ptr += sizeof(UA_Int32) + (member->padding & 0x07);
  638. *((void**)ptr) = UA_NULL;
  639. ptr += sizeof(void*);
  640. continue;
  641. }
  642. ptr += member->padding;
  643. if(!member->namespaceZero) {
  644. // pointer arithmetic
  645. const UA_DataType *memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  646. UA_init((void*)ptr, memberType);
  647. ptr += memberType->memSize;
  648. continue;
  649. }
  650. switch(member->memberTypeIndex) {
  651. case UA_TYPES_BOOLEAN:
  652. case UA_TYPES_SBYTE:
  653. case UA_TYPES_BYTE:
  654. *(UA_Byte*)ptr = 0;
  655. break;
  656. case UA_TYPES_INT16:
  657. case UA_TYPES_UINT16:
  658. *(UA_Int16*)ptr = 0;
  659. break;
  660. case UA_TYPES_INT32:
  661. case UA_TYPES_UINT32:
  662. case UA_TYPES_STATUSCODE:
  663. case UA_TYPES_FLOAT:
  664. *(UA_Int32*)ptr = 0;
  665. break;
  666. case UA_TYPES_INT64:
  667. case UA_TYPES_UINT64:
  668. case UA_TYPES_DOUBLE:
  669. case UA_TYPES_DATETIME:
  670. *(UA_Int64*)ptr = 0;
  671. break;
  672. case UA_TYPES_GUID:
  673. UA_Guid_init((UA_Guid*)ptr);
  674. break;
  675. case UA_TYPES_NODEID:
  676. UA_NodeId_init((UA_NodeId*)ptr);
  677. break;
  678. case UA_TYPES_EXPANDEDNODEID:
  679. UA_ExpandedNodeId_init((UA_ExpandedNodeId*)ptr);
  680. break;
  681. case UA_TYPES_QUALIFIEDNAME:
  682. UA_QualifiedName_init((UA_QualifiedName*)ptr);
  683. break;
  684. case UA_TYPES_LOCALIZEDTEXT:
  685. UA_LocalizedText_init((UA_LocalizedText*)ptr);
  686. break;
  687. case UA_TYPES_EXTENSIONOBJECT:
  688. UA_ExtensionObject_init((UA_ExtensionObject*)ptr);
  689. break;
  690. case UA_TYPES_DATAVALUE:
  691. UA_DataValue_init((UA_DataValue*)ptr);
  692. break;
  693. case UA_TYPES_VARIANT:
  694. UA_Variant_init((UA_Variant*)ptr);
  695. break;
  696. case UA_TYPES_DIAGNOSTICINFO:
  697. UA_DiagnosticInfo_init((UA_DiagnosticInfo*)ptr);
  698. break;
  699. case UA_TYPES_STRING:
  700. case UA_TYPES_BYTESTRING:
  701. case UA_TYPES_XMLELEMENT:
  702. UA_String_init((UA_String*)ptr);
  703. break;
  704. default:
  705. UA_init((void*)ptr, &UA_TYPES[member->memberTypeIndex]);
  706. }
  707. ptr += UA_TYPES[member->memberTypeIndex].memSize;
  708. }
  709. }
  710. void * UA_new(const UA_DataType *dataType) {
  711. void *p = UA_malloc(dataType->memSize);
  712. if(p)
  713. UA_init(p, dataType);
  714. return p;
  715. }
  716. UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *dataType) {
  717. if(dataType->fixedSize) {
  718. memcpy(dst, src, dataType->memSize);
  719. return UA_STATUSCODE_GOOD;
  720. }
  721. UA_init(dst, dataType);
  722. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  723. uintptr_t ptrs = (uintptr_t)src;
  724. uintptr_t ptrd = (uintptr_t)dst;
  725. UA_Byte membersSize = dataType->membersSize;
  726. for(size_t i=0;i<membersSize; i++) {
  727. const UA_DataTypeMember *member = &dataType->members[i];
  728. const UA_DataType *memberType;
  729. if(member->namespaceZero)
  730. memberType = &UA_TYPES[member->memberTypeIndex];
  731. else
  732. memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  733. if(member->isArray) {
  734. ptrs += (member->padding >> 3);
  735. ptrd += (member->padding >> 3);
  736. UA_Int32 *dstNoElements = (UA_Int32*)ptrd;
  737. const UA_Int32 noElements = *((const UA_Int32*)ptrs);
  738. ptrs += sizeof(UA_Int32) + (member->padding & 0x07);
  739. ptrd += sizeof(UA_Int32) + (member->padding & 0x07);
  740. retval = UA_Array_copy(*(void* const*)ptrs, (void**)ptrd, memberType, noElements);
  741. if(retval != UA_STATUSCODE_GOOD) {
  742. UA_deleteMembers(dst, dataType);
  743. UA_init(dst, dataType);
  744. return retval;
  745. }
  746. *dstNoElements = noElements;
  747. ptrs += sizeof(void*);
  748. ptrd += sizeof(void*);
  749. continue;
  750. }
  751. ptrs += member->padding;
  752. ptrd += member->padding;
  753. if(!member->namespaceZero) {
  754. retval = UA_copy((const void*)ptrs, (void*)ptrd, memberType);
  755. if(retval != UA_STATUSCODE_GOOD) {
  756. UA_deleteMembers(dst, dataType);
  757. UA_init(dst, dataType);
  758. return retval;
  759. }
  760. ptrs += memberType->memSize;
  761. ptrd += memberType->memSize;
  762. continue;
  763. }
  764. switch(member->memberTypeIndex) {
  765. case UA_TYPES_BOOLEAN:
  766. case UA_TYPES_SBYTE:
  767. case UA_TYPES_BYTE:
  768. *((UA_Byte*)ptrd) = *((const UA_Byte*)ptrs);
  769. break;
  770. case UA_TYPES_INT16:
  771. case UA_TYPES_UINT16:
  772. *((UA_Int16*)ptrd) = *((const UA_Byte*)ptrs);
  773. break;
  774. case UA_TYPES_INT32:
  775. case UA_TYPES_UINT32:
  776. case UA_TYPES_STATUSCODE:
  777. case UA_TYPES_FLOAT:
  778. *((UA_Int32*)ptrd) = *((const UA_Int32*)ptrs);
  779. break;
  780. case UA_TYPES_INT64:
  781. case UA_TYPES_UINT64:
  782. case UA_TYPES_DOUBLE:
  783. case UA_TYPES_DATETIME:
  784. *((UA_Int64*)ptrd) = *((const UA_Int64*)ptrs);
  785. break;
  786. case UA_TYPES_GUID:
  787. *((UA_Guid*)ptrd) = *((const UA_Guid*)ptrs);
  788. break;
  789. case UA_TYPES_NODEID:
  790. retval |= UA_NodeId_copy((const UA_NodeId*)ptrs, (UA_NodeId*)ptrd);
  791. break;
  792. case UA_TYPES_EXPANDEDNODEID:
  793. retval |= UA_ExpandedNodeId_copy((const UA_ExpandedNodeId*)ptrs, (UA_ExpandedNodeId*)ptrd);
  794. break;
  795. case UA_TYPES_QUALIFIEDNAME:
  796. retval |= UA_QualifiedName_copy((const UA_QualifiedName*)ptrs, (UA_QualifiedName*)ptrd);
  797. break;
  798. case UA_TYPES_LOCALIZEDTEXT:
  799. retval |= UA_LocalizedText_copy((const UA_LocalizedText*)ptrs, (UA_LocalizedText*)ptrd);
  800. break;
  801. case UA_TYPES_EXTENSIONOBJECT:
  802. retval |= UA_ExtensionObject_copy((const UA_ExtensionObject*)ptrs, (UA_ExtensionObject*)ptrd);
  803. break;
  804. case UA_TYPES_DATAVALUE:
  805. retval |= UA_DataValue_copy((const UA_DataValue*)ptrs, (UA_DataValue*)ptrd);
  806. break;
  807. case UA_TYPES_VARIANT:
  808. retval |= UA_Variant_copy((const UA_Variant*)ptrs, (UA_Variant*)ptrd);
  809. break;
  810. case UA_TYPES_DIAGNOSTICINFO:
  811. retval |= UA_DiagnosticInfo_copy((const UA_DiagnosticInfo*)ptrs, (UA_DiagnosticInfo*)ptrd);
  812. break;
  813. case UA_TYPES_STRING:
  814. case UA_TYPES_BYTESTRING:
  815. case UA_TYPES_XMLELEMENT:
  816. retval |= UA_String_copy((const UA_String*)ptrs, (UA_String*)ptrd);
  817. break;
  818. default:
  819. retval |= UA_copy((const void *)ptrs, (void*)ptrd, memberType);
  820. }
  821. ptrs += memberType->memSize;
  822. ptrd += memberType->memSize;
  823. }
  824. if(retval != UA_STATUSCODE_GOOD) {
  825. UA_deleteMembers(dst, dataType);
  826. UA_init(dst, dataType);
  827. }
  828. return retval;
  829. }
  830. void UA_deleteMembers(void *p, const UA_DataType *dataType) {
  831. uintptr_t ptr = (uintptr_t)p;
  832. if(dataType->fixedSize)
  833. return;
  834. UA_Byte membersSize = dataType->membersSize;
  835. for(size_t i=0;i<membersSize; i++) {
  836. const UA_DataTypeMember *member = &dataType->members[i];
  837. const UA_DataType *memberType;
  838. if(member->namespaceZero)
  839. memberType = &UA_TYPES[member->memberTypeIndex];
  840. else
  841. memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
  842. if(member->isArray) {
  843. ptr += (member->padding >> 3);
  844. UA_Int32 noElements = *((UA_Int32*)ptr);
  845. ptr += sizeof(UA_Int32) + (member->padding & 0x07);
  846. UA_Array_delete(*(void**)ptr, memberType, noElements);
  847. ptr += sizeof(void*);
  848. continue;
  849. }
  850. ptr += member->padding;
  851. if(!member->namespaceZero) {
  852. UA_deleteMembers((void*)ptr, memberType);
  853. ptr += memberType->memSize;
  854. continue;
  855. }
  856. switch(member->memberTypeIndex) {
  857. // the following types have a fixed size.
  858. /* UA_BOOLEAN, UA_SBYTE, UA_BYTE, UA_INT16, UA_UINT16, UA_INT32, UA_UINT32, */
  859. /* UA_STATUSCODE, UA_FLOAT, UA_INT64, UA_UINT64, UA_DOUBLE, UA_DATETIME, UA_GUID */
  860. case UA_TYPES_NODEID:
  861. UA_NodeId_deleteMembers((UA_NodeId*)ptr);
  862. break;
  863. case UA_TYPES_EXPANDEDNODEID:
  864. UA_ExpandedNodeId_deleteMembers((UA_ExpandedNodeId*)ptr);
  865. break;
  866. case UA_TYPES_QUALIFIEDNAME:
  867. UA_QualifiedName_deleteMembers((UA_QualifiedName*)ptr);
  868. break;
  869. case UA_TYPES_LOCALIZEDTEXT:
  870. UA_LocalizedText_deleteMembers((UA_LocalizedText*)ptr);
  871. break;
  872. case UA_TYPES_EXTENSIONOBJECT:
  873. UA_ExtensionObject_deleteMembers((UA_ExtensionObject*)ptr);
  874. break;
  875. case UA_TYPES_DATAVALUE:
  876. UA_DataValue_deleteMembers((UA_DataValue*)ptr);
  877. break;
  878. case UA_TYPES_VARIANT:
  879. UA_Variant_deleteMembers((UA_Variant*)ptr);
  880. break;
  881. case UA_TYPES_DIAGNOSTICINFO:
  882. UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
  883. break;
  884. case UA_TYPES_STRING:
  885. case UA_TYPES_BYTESTRING:
  886. case UA_TYPES_XMLELEMENT:
  887. UA_String_deleteMembers((UA_String*)ptr);
  888. break;
  889. default:
  890. UA_deleteMembers((void*)ptr, memberType);
  891. }
  892. ptr += memberType->memSize;
  893. }
  894. }
  895. void UA_delete(void *p, const UA_DataType *dataType) {
  896. UA_deleteMembers(p, dataType);
  897. UA_free(p);
  898. }
  899. /******************/
  900. /* Array Handling */
  901. /******************/
  902. void* UA_Array_new(const UA_DataType *dataType, UA_Int32 noElements) {
  903. if(noElements <= 0)
  904. return UA_NULL;
  905. if((UA_Int32)dataType->memSize * noElements < 0 || dataType->memSize * noElements > MAX_ARRAY_SIZE )
  906. return UA_NULL;
  907. void *p = malloc(dataType->memSize * (size_t)noElements);
  908. if(!p || dataType->fixedSize) // datatypes of fixed size are not initialized.
  909. return p;
  910. uintptr_t ptr = (uintptr_t)p;
  911. for(int i = 0; i<noElements; i++) {
  912. UA_init((void*)ptr, dataType);
  913. ptr += dataType->memSize;
  914. }
  915. return p;
  916. }
  917. UA_StatusCode UA_Array_copy(const void *src, void **dst, const UA_DataType *dataType, UA_Int32 noElements) {
  918. if(noElements <= 0) {
  919. *dst = UA_NULL;
  920. return UA_STATUSCODE_GOOD;
  921. }
  922. if(!(*dst = UA_malloc((size_t)noElements * dataType->memSize)))
  923. return UA_STATUSCODE_BADOUTOFMEMORY;
  924. if(dataType->fixedSize) {
  925. memcpy(*dst, src, dataType->memSize * (size_t)noElements);
  926. return UA_STATUSCODE_GOOD;
  927. }
  928. uintptr_t ptrs = (uintptr_t)src;
  929. uintptr_t ptrd = (uintptr_t)*dst;
  930. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  931. for(int i=0;i<noElements; i++) {
  932. retval = UA_copy((void*)ptrs, (void*)ptrd, dataType);
  933. ptrs += dataType->memSize;
  934. ptrd += dataType->memSize;
  935. }
  936. if(retval != UA_STATUSCODE_GOOD)
  937. UA_Array_delete(*dst, dataType, noElements);
  938. return retval;
  939. }
  940. void UA_Array_delete(void *p, const UA_DataType *dataType, UA_Int32 noElements) {
  941. if(noElements <= 0 || !p)
  942. return;
  943. if(!dataType->fixedSize) {
  944. uintptr_t ptr = (uintptr_t)p;
  945. for(UA_Int32 i = 0; i<noElements; i++) {
  946. UA_deleteMembers((void*)ptr, dataType);
  947. ptr += dataType->memSize;
  948. }
  949. }
  950. UA_free(p);
  951. }