ua_types.c 39 KB

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