ua_types.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014, 2016-2017 (c) Florian Palm
  7. * Copyright 2014-2016 (c) Sten Grüner
  8. * Copyright 2014 (c) Leon Urbas
  9. * Copyright 2015 (c) Chris Iatrou
  10. * Copyright 2015 (c) Markus Graube
  11. * Copyright 2015 (c) Reza Ebrahimi
  12. * Copyright 2015-2016 (c) Oleksiy Vasylyev
  13. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  14. * Copyright 2016 (c) Lorenz Haas
  15. */
  16. #include "ua_util_internal.h"
  17. #include "ua_types.h"
  18. #include "ua_types_generated.h"
  19. #include "ua_types_generated_handling.h"
  20. #include "pcg_basic.h"
  21. #include "libc_time.h"
  22. /* Datatype Handling
  23. * -----------------
  24. * This file contains handling functions for the builtin types and functions
  25. * handling of structured types and arrays. These need type descriptions in a
  26. * UA_DataType structure. The UA_DataType structures as well as all non-builtin
  27. * datatypes are autogenerated. */
  28. /* Global definition of NULL type instances. These are always zeroed out, as
  29. * mandated by the C/C++ standard for global values with no initializer. */
  30. const UA_String UA_STRING_NULL = {0, NULL};
  31. const UA_ByteString UA_BYTESTRING_NULL = {0, NULL};
  32. const UA_Guid UA_GUID_NULL = {0, 0, 0, {0,0,0,0,0,0,0,0}};
  33. const UA_NodeId UA_NODEID_NULL = {0, UA_NODEIDTYPE_NUMERIC, {0}};
  34. const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {{0, UA_NODEIDTYPE_NUMERIC, {0}}, {0, NULL}, 0};
  35. /* TODO: The standard-defined types are ordered. See if binary search is
  36. * more efficient. */
  37. const UA_DataType *
  38. UA_findDataType(const UA_NodeId *typeId) {
  39. if(typeId->identifierType != UA_NODEIDTYPE_NUMERIC)
  40. return NULL;
  41. /* Always look in built-in types first
  42. * (may contain data types from all namespaces) */
  43. for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
  44. if(UA_TYPES[i].typeId.identifier.numeric == typeId->identifier.numeric
  45. && UA_TYPES[i].typeId.namespaceIndex == typeId->namespaceIndex)
  46. return &UA_TYPES[i];
  47. }
  48. /* TODO When other namespace look in custom types, too, requires access to custom types array here! */
  49. /*if(typeId->namespaceIndex != 0) {
  50. size_t customTypesArraySize;
  51. const UA_DataType *customTypesArray;
  52. UA_getCustomTypes(&customTypesArraySize, &customTypesArray);
  53. for(size_t i = 0; i < customTypesArraySize; ++i) {
  54. if(customTypesArray[i].typeId.identifier.numeric == typeId->identifier.numeric
  55. && customTypesArray[i].typeId.namespaceIndex == typeId->namespaceIndex)
  56. return &customTypesArray[i];
  57. }
  58. }*/
  59. return NULL;
  60. }
  61. /***************************/
  62. /* Random Number Generator */
  63. /***************************/
  64. //TODO is this safe for multithreading?
  65. static pcg32_random_t UA_rng = PCG32_INITIALIZER;
  66. void
  67. UA_random_seed(u64 seed) {
  68. pcg32_srandom_r(&UA_rng, seed, (u64)UA_DateTime_now());
  69. }
  70. u32
  71. UA_UInt32_random(void) {
  72. return (u32)pcg32_random_r(&UA_rng);
  73. }
  74. /*****************/
  75. /* Builtin Types */
  76. /*****************/
  77. static void clear_noInit(void *p, const UA_DataType *type);
  78. static UA_StatusCode copy_noInit(const void *src, void *dst, const UA_DataType *type);
  79. UA_String
  80. UA_String_fromChars(char const src[]) {
  81. UA_String str;
  82. str.length = strlen(src);
  83. if(str.length > 0) {
  84. str.data = (u8*)UA_malloc(str.length);
  85. if(!str.data)
  86. return UA_STRING_NULL;
  87. memcpy(str.data, src, str.length);
  88. } else {
  89. str.data = (u8*)UA_EMPTY_ARRAY_SENTINEL;
  90. }
  91. return str;
  92. }
  93. UA_Boolean
  94. UA_String_equal(const UA_String *s1, const UA_String *s2) {
  95. if(s1->length != s2->length)
  96. return false;
  97. i32 is = memcmp((char const*)s1->data,
  98. (char const*)s2->data, s1->length);
  99. return (is == 0) ? true : false;
  100. }
  101. static UA_StatusCode
  102. String_copy(UA_String const *src, UA_String *dst, const UA_DataType *_) {
  103. UA_StatusCode retval = UA_Array_copy(src->data, src->length, (void**)&dst->data,
  104. &UA_TYPES[UA_TYPES_BYTE]);
  105. if(retval == UA_STATUSCODE_GOOD)
  106. dst->length = src->length;
  107. return retval;
  108. }
  109. static void
  110. String_clear(UA_String *s, const UA_DataType *_) {
  111. UA_Array_delete(s->data, s->length, &UA_TYPES[UA_TYPES_BYTE]);
  112. }
  113. /* QualifiedName */
  114. static UA_StatusCode
  115. QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst, const UA_DataType *_) {
  116. dst->namespaceIndex = src->namespaceIndex;
  117. return String_copy(&src->name, &dst->name, NULL);
  118. }
  119. static void
  120. QualifiedName_clear(UA_QualifiedName *p, const UA_DataType *_) {
  121. String_clear(&p->name, NULL);
  122. }
  123. UA_Boolean
  124. UA_QualifiedName_equal(const UA_QualifiedName *qn1,
  125. const UA_QualifiedName *qn2) {
  126. if(qn1 == NULL || qn2 == NULL)
  127. return false;
  128. if(qn1->namespaceIndex != qn2->namespaceIndex)
  129. return false;
  130. if(qn1->name.length != qn2->name.length)
  131. return false;
  132. return (memcmp((char const*)qn1->name.data,
  133. (char const*)qn2->name.data, qn1->name.length) == 0);
  134. }
  135. /* DateTime */
  136. UA_DateTimeStruct
  137. UA_DateTime_toStruct(UA_DateTime t) {
  138. /* Calculating the the milli-, micro- and nanoseconds */
  139. UA_DateTimeStruct dateTimeStruct;
  140. dateTimeStruct.nanoSec = (u16)((t % 10) * 100);
  141. dateTimeStruct.microSec = (u16)((t % 10000) / 10);
  142. dateTimeStruct.milliSec = (u16)((t % 10000000) / 10000);
  143. /* Calculating the unix time with #include <time.h> */
  144. long long secSinceUnixEpoch = (long long)
  145. ((t - UA_DATETIME_UNIX_EPOCH) / UA_DATETIME_SEC);
  146. struct mytm ts;
  147. memset(&ts, 0, sizeof(struct mytm));
  148. __secs_to_tm(secSinceUnixEpoch, &ts);
  149. dateTimeStruct.sec = (u16)ts.tm_sec;
  150. dateTimeStruct.min = (u16)ts.tm_min;
  151. dateTimeStruct.hour = (u16)ts.tm_hour;
  152. dateTimeStruct.day = (u16)ts.tm_mday;
  153. dateTimeStruct.month = (u16)(ts.tm_mon + 1);
  154. dateTimeStruct.year = (u16)(ts.tm_year + 1900);
  155. return dateTimeStruct;
  156. }
  157. /* Guid */
  158. UA_Boolean
  159. UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
  160. if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
  161. return true;
  162. return false;
  163. }
  164. UA_Guid
  165. UA_Guid_random(void) {
  166. UA_Guid result;
  167. result.data1 = (u32)pcg32_random_r(&UA_rng);
  168. u32 r = (u32)pcg32_random_r(&UA_rng);
  169. result.data2 = (u16) r;
  170. result.data3 = (u16) (r >> 16);
  171. r = (u32)pcg32_random_r(&UA_rng);
  172. result.data4[0] = (u8)r;
  173. result.data4[1] = (u8)(r >> 4);
  174. result.data4[2] = (u8)(r >> 8);
  175. result.data4[3] = (u8)(r >> 12);
  176. r = (u32)pcg32_random_r(&UA_rng);
  177. result.data4[4] = (u8)r;
  178. result.data4[5] = (u8)(r >> 4);
  179. result.data4[6] = (u8)(r >> 8);
  180. result.data4[7] = (u8)(r >> 12);
  181. return result;
  182. }
  183. /* ByteString */
  184. UA_StatusCode
  185. UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
  186. UA_ByteString_init(bs);
  187. if(length == 0)
  188. return UA_STATUSCODE_GOOD;
  189. bs->data = (u8*)UA_malloc(length);
  190. if(!bs->data)
  191. return UA_STATUSCODE_BADOUTOFMEMORY;
  192. bs->length = length;
  193. return UA_STATUSCODE_GOOD;
  194. }
  195. /* NodeId */
  196. static void
  197. NodeId_clear(UA_NodeId *p, const UA_DataType *_) {
  198. switch(p->identifierType) {
  199. case UA_NODEIDTYPE_STRING:
  200. case UA_NODEIDTYPE_BYTESTRING:
  201. String_clear(&p->identifier.string, NULL);
  202. break;
  203. default: break;
  204. }
  205. }
  206. static UA_StatusCode
  207. NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_DataType *_) {
  208. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  209. switch(src->identifierType) {
  210. case UA_NODEIDTYPE_NUMERIC:
  211. *dst = *src;
  212. return UA_STATUSCODE_GOOD;
  213. case UA_NODEIDTYPE_STRING:
  214. retval |= UA_String_copy(&src->identifier.string,
  215. &dst->identifier.string);
  216. break;
  217. case UA_NODEIDTYPE_GUID:
  218. retval |= UA_Guid_copy(&src->identifier.guid, &dst->identifier.guid);
  219. break;
  220. case UA_NODEIDTYPE_BYTESTRING:
  221. retval |= UA_ByteString_copy(&src->identifier.byteString,
  222. &dst->identifier.byteString);
  223. break;
  224. default:
  225. return UA_STATUSCODE_BADINTERNALERROR;
  226. }
  227. dst->namespaceIndex = src->namespaceIndex;
  228. dst->identifierType = src->identifierType;
  229. return retval;
  230. }
  231. UA_Boolean
  232. UA_NodeId_isNull(const UA_NodeId *p) {
  233. if(p->namespaceIndex != 0)
  234. return false;
  235. switch (p->identifierType) {
  236. case UA_NODEIDTYPE_NUMERIC:
  237. return (p->identifier.numeric == 0);
  238. case UA_NODEIDTYPE_STRING:
  239. return UA_String_equal(&p->identifier.string, &UA_STRING_NULL);
  240. case UA_NODEIDTYPE_GUID:
  241. return UA_Guid_equal(&p->identifier.guid, &UA_GUID_NULL);
  242. case UA_NODEIDTYPE_BYTESTRING:
  243. return UA_ByteString_equal(&p->identifier.byteString, &UA_BYTESTRING_NULL);
  244. }
  245. return false;
  246. }
  247. UA_Boolean
  248. UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
  249. if(n1 == NULL || n2 == NULL)
  250. return false;
  251. if(n1->namespaceIndex != n2->namespaceIndex ||
  252. n1->identifierType!=n2->identifierType)
  253. return false;
  254. switch(n1->identifierType) {
  255. case UA_NODEIDTYPE_NUMERIC:
  256. return (n1->identifier.numeric == n2->identifier.numeric);
  257. case UA_NODEIDTYPE_STRING:
  258. return UA_String_equal(&n1->identifier.string,
  259. &n2->identifier.string);
  260. case UA_NODEIDTYPE_GUID:
  261. return UA_Guid_equal(&n1->identifier.guid,
  262. &n2->identifier.guid);
  263. case UA_NODEIDTYPE_BYTESTRING:
  264. return UA_ByteString_equal(&n1->identifier.byteString,
  265. &n2->identifier.byteString);
  266. }
  267. return false;
  268. }
  269. UA_Boolean
  270. UA_ExpandedNodeId_equal(const UA_ExpandedNodeId *n1, const UA_ExpandedNodeId *n2) {
  271. if(n1 == NULL || n2 == NULL)
  272. return false;
  273. if(n1->serverIndex != n2->serverIndex)
  274. return false;
  275. if(!UA_String_equal(&n1->namespaceUri, &n2->namespaceUri))
  276. return false;
  277. return UA_NodeId_equal(&n1->nodeId, &n2->nodeId);
  278. }
  279. /* FNV non-cryptographic hash function. See
  280. * https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */
  281. #define FNV_PRIME_32 16777619
  282. static u32
  283. fnv32(u32 fnv, const u8 *buf, size_t size) {
  284. for(size_t i = 0; i < size; ++i) {
  285. fnv = fnv ^ (buf[i]);
  286. fnv = fnv * FNV_PRIME_32;
  287. }
  288. return fnv;
  289. }
  290. u32
  291. UA_NodeId_hash(const UA_NodeId *n) {
  292. switch(n->identifierType) {
  293. case UA_NODEIDTYPE_NUMERIC:
  294. default:
  295. // shift knuth multiplication to use highest 32 bits and after addition make sure we don't have an integer overflow
  296. return (u32)((n->namespaceIndex + ((n->identifier.numeric * (u64)2654435761) >> (32))) & UINT32_C(4294967295)); /* Knuth's multiplicative hashing */
  297. case UA_NODEIDTYPE_STRING:
  298. case UA_NODEIDTYPE_BYTESTRING:
  299. return fnv32(n->namespaceIndex, n->identifier.string.data, n->identifier.string.length);
  300. case UA_NODEIDTYPE_GUID:
  301. return fnv32(n->namespaceIndex, (const u8*)&n->identifier.guid, sizeof(UA_Guid));
  302. }
  303. }
  304. /* ExpandedNodeId */
  305. static void
  306. ExpandedNodeId_clear(UA_ExpandedNodeId *p, const UA_DataType *_) {
  307. NodeId_clear(&p->nodeId, _);
  308. String_clear(&p->namespaceUri, NULL);
  309. }
  310. static UA_StatusCode
  311. ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst,
  312. const UA_DataType *_) {
  313. UA_StatusCode retval = NodeId_copy(&src->nodeId, &dst->nodeId, NULL);
  314. retval |= UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
  315. dst->serverIndex = src->serverIndex;
  316. return retval;
  317. }
  318. /* ExtensionObject */
  319. static void
  320. ExtensionObject_clear(UA_ExtensionObject *p, const UA_DataType *_) {
  321. switch(p->encoding) {
  322. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  323. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  324. case UA_EXTENSIONOBJECT_ENCODED_XML:
  325. NodeId_clear(&p->content.encoded.typeId, NULL);
  326. String_clear(&p->content.encoded.body, NULL);
  327. break;
  328. case UA_EXTENSIONOBJECT_DECODED:
  329. if(p->content.decoded.data)
  330. UA_delete(p->content.decoded.data, p->content.decoded.type);
  331. break;
  332. default:
  333. break;
  334. }
  335. }
  336. static UA_StatusCode
  337. ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst,
  338. const UA_DataType *_) {
  339. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  340. switch(src->encoding) {
  341. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  342. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  343. case UA_EXTENSIONOBJECT_ENCODED_XML:
  344. dst->encoding = src->encoding;
  345. retval = NodeId_copy(&src->content.encoded.typeId,
  346. &dst->content.encoded.typeId, NULL);
  347. retval |= UA_ByteString_copy(&src->content.encoded.body,
  348. &dst->content.encoded.body);
  349. break;
  350. case UA_EXTENSIONOBJECT_DECODED:
  351. case UA_EXTENSIONOBJECT_DECODED_NODELETE:
  352. if(!src->content.decoded.type || !src->content.decoded.data)
  353. return UA_STATUSCODE_BADINTERNALERROR;
  354. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  355. dst->content.decoded.type = src->content.decoded.type;
  356. retval = UA_Array_copy(src->content.decoded.data, 1,
  357. &dst->content.decoded.data, src->content.decoded.type);
  358. break;
  359. default:
  360. break;
  361. }
  362. return retval;
  363. }
  364. /* Variant */
  365. static void
  366. Variant_clear(UA_Variant *p, const UA_DataType *_) {
  367. if(p->storageType != UA_VARIANT_DATA)
  368. return;
  369. if(p->type && p->data > UA_EMPTY_ARRAY_SENTINEL) {
  370. if(p->arrayLength == 0)
  371. p->arrayLength = 1;
  372. UA_Array_delete(p->data, p->arrayLength, p->type);
  373. p->data = NULL;
  374. }
  375. if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
  376. UA_free(p->arrayDimensions);
  377. }
  378. static UA_StatusCode
  379. Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) {
  380. size_t length = src->arrayLength;
  381. if(UA_Variant_isScalar(src))
  382. length = 1;
  383. UA_StatusCode retval = UA_Array_copy(src->data, length,
  384. &dst->data, src->type);
  385. if(retval != UA_STATUSCODE_GOOD)
  386. return retval;
  387. dst->arrayLength = src->arrayLength;
  388. dst->type = src->type;
  389. if(src->arrayDimensions) {
  390. retval = UA_Array_copy(src->arrayDimensions, src->arrayDimensionsSize,
  391. (void**)&dst->arrayDimensions, &UA_TYPES[UA_TYPES_INT32]);
  392. if(retval != UA_STATUSCODE_GOOD)
  393. return retval;
  394. dst->arrayDimensionsSize = src->arrayDimensionsSize;
  395. }
  396. return UA_STATUSCODE_GOOD;
  397. }
  398. void
  399. UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
  400. const UA_DataType *type) {
  401. UA_Variant_init(v);
  402. v->type = type;
  403. v->arrayLength = 0;
  404. v->data = p;
  405. }
  406. UA_StatusCode
  407. UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
  408. const UA_DataType *type) {
  409. void *n = UA_malloc(type->memSize);
  410. if(!n)
  411. return UA_STATUSCODE_BADOUTOFMEMORY;
  412. UA_StatusCode retval = UA_copy(p, n, type);
  413. if(retval != UA_STATUSCODE_GOOD) {
  414. UA_free(n);
  415. //cppcheck-suppress memleak
  416. return retval;
  417. }
  418. UA_Variant_setScalar(v, n, type);
  419. //cppcheck-suppress memleak
  420. return UA_STATUSCODE_GOOD;
  421. }
  422. void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
  423. size_t arraySize, const UA_DataType *type) {
  424. UA_Variant_init(v);
  425. v->data = array;
  426. v->arrayLength = arraySize;
  427. v->type = type;
  428. }
  429. UA_StatusCode
  430. UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
  431. size_t arraySize, const UA_DataType *type) {
  432. UA_Variant_init(v);
  433. UA_StatusCode retval = UA_Array_copy(array, arraySize, &v->data, type);
  434. if(retval != UA_STATUSCODE_GOOD)
  435. return retval;
  436. v->arrayLength = arraySize;
  437. v->type = type;
  438. return UA_STATUSCODE_GOOD;
  439. }
  440. /* Test if a range is compatible with a variant. If yes, the following values
  441. * are set:
  442. * - total: how many elements are in the range
  443. * - block: how big is each contiguous block of elements in the variant that
  444. * maps into the range
  445. * - stride: how many elements are between the blocks (beginning to beginning)
  446. * - first: where does the first block begin */
  447. static UA_StatusCode
  448. computeStrides(const UA_Variant *v, const UA_NumericRange range,
  449. size_t *total, size_t *block, size_t *stride, size_t *first) {
  450. /* Test for max array size (64bit only) */
  451. #if (SIZE_MAX > 0xffffffff)
  452. if(v->arrayLength > UA_UINT32_MAX)
  453. return UA_STATUSCODE_BADINTERNALERROR;
  454. #endif
  455. /* Test the integrity of the source variant dimensions, make dimensions
  456. * vector of one dimension if none defined */
  457. u32 arrayLength = (u32)v->arrayLength;
  458. const u32 *dims = &arrayLength;
  459. size_t dims_count = 1;
  460. if(v->arrayDimensionsSize > 0) {
  461. size_t elements = 1;
  462. dims_count = v->arrayDimensionsSize;
  463. dims = (u32*)v->arrayDimensions;
  464. for(size_t i = 0; i < dims_count; ++i)
  465. elements *= dims[i];
  466. if(elements != v->arrayLength)
  467. return UA_STATUSCODE_BADINTERNALERROR;
  468. }
  469. UA_assert(dims_count > 0);
  470. /* Test the integrity of the range and compute the max index used for every
  471. * dimension. The standard says in Part 4, Section 7.22:
  472. *
  473. * When reading a value, the indexes may not specify a range that is within
  474. * the bounds of the array. The Server shall return a partial result if some
  475. * elements exist within the range. */
  476. size_t count = 1;
  477. UA_STACKARRAY(UA_UInt32, realmax, dims_count);
  478. if(range.dimensionsSize != dims_count)
  479. return UA_STATUSCODE_BADINDEXRANGENODATA;
  480. for(size_t i = 0; i < dims_count; ++i) {
  481. if(range.dimensions[i].min > range.dimensions[i].max)
  482. return UA_STATUSCODE_BADINDEXRANGEINVALID;
  483. if(range.dimensions[i].min >= dims[i])
  484. return UA_STATUSCODE_BADINDEXRANGENODATA;
  485. if(range.dimensions[i].max < dims[i])
  486. realmax[i] = range.dimensions[i].max;
  487. else
  488. realmax[i] = dims[i] - 1;
  489. count *= (realmax[i] - range.dimensions[i].min) + 1;
  490. }
  491. *total = count;
  492. /* Compute the stride length and the position of the first element */
  493. *block = count; /* Assume the range describes the entire array. */
  494. *stride = v->arrayLength; /* So it can be copied as a contiguous block. */
  495. *first = 0;
  496. size_t running_dimssize = 1;
  497. UA_Boolean found_contiguous = false;
  498. for(size_t k = dims_count; k > 0;) {
  499. --k;
  500. size_t dimrange = 1 + realmax[k] - range.dimensions[k].min;
  501. if(!found_contiguous && dimrange != dims[k]) {
  502. /* Found the maximum block that can be copied contiguously */
  503. found_contiguous = true;
  504. *block = running_dimssize * dimrange;
  505. *stride = running_dimssize * dims[k];
  506. }
  507. *first += running_dimssize * range.dimensions[k].min;
  508. running_dimssize *= dims[k];
  509. }
  510. return UA_STATUSCODE_GOOD;
  511. }
  512. /* Is the type string-like? */
  513. static UA_Boolean
  514. isStringLike(const UA_DataType *type) {
  515. if(type == &UA_TYPES[UA_TYPES_STRING] ||
  516. type == &UA_TYPES[UA_TYPES_BYTESTRING] ||
  517. type == &UA_TYPES[UA_TYPES_XMLELEMENT])
  518. return true;
  519. return false;
  520. }
  521. /* Returns the part of the string that lies within the rangedimension */
  522. static UA_StatusCode
  523. copySubString(const UA_String *src, UA_String *dst,
  524. const UA_NumericRangeDimension *dim) {
  525. if(dim->min > dim->max)
  526. return UA_STATUSCODE_BADINDEXRANGEINVALID;
  527. if(dim->min >= src->length)
  528. return UA_STATUSCODE_BADINDEXRANGENODATA;
  529. size_t length;
  530. if(dim->max < src->length)
  531. length = dim->max - dim->min + 1;
  532. else
  533. length = src->length - dim->min;
  534. UA_StatusCode retval = UA_ByteString_allocBuffer(dst, length);
  535. if(retval != UA_STATUSCODE_GOOD)
  536. return retval;
  537. memcpy(dst->data, &src->data[dim->min], length);
  538. return UA_STATUSCODE_GOOD;
  539. }
  540. UA_StatusCode
  541. UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
  542. const UA_NumericRange range) {
  543. if(!src->type)
  544. return UA_STATUSCODE_BADINVALIDARGUMENT;
  545. UA_Boolean isScalar = UA_Variant_isScalar(src);
  546. UA_Boolean stringLike = isStringLike(src->type);
  547. UA_Variant arraySrc;
  548. /* Extract the range for copying at this level. The remaining range is dealt
  549. * with in the "scalar" type that may define an array by itself (string,
  550. * variant, ...). */
  551. UA_NumericRange thisrange, nextrange;
  552. UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */
  553. if(isScalar) {
  554. /* Replace scalar src with array of length 1 */
  555. arraySrc = *src;
  556. arraySrc.arrayLength = 1;
  557. src = &arraySrc;
  558. /* Deal with all range dimensions within the scalar */
  559. thisrange.dimensions = &scalarThisDimension;
  560. thisrange.dimensionsSize = 1;
  561. nextrange = range;
  562. } else {
  563. /* Deal with as many range dimensions as possible right now */
  564. size_t dims = src->arrayDimensionsSize;
  565. if(dims == 0)
  566. dims = 1;
  567. if(dims > range.dimensionsSize)
  568. return UA_STATUSCODE_BADINDEXRANGEINVALID;
  569. thisrange = range;
  570. thisrange.dimensionsSize = dims;
  571. nextrange.dimensions = &range.dimensions[dims];
  572. nextrange.dimensionsSize = range.dimensionsSize - dims;
  573. }
  574. /* Compute the strides */
  575. size_t count, block, stride, first;
  576. UA_StatusCode retval = computeStrides(src, thisrange, &count,
  577. &block, &stride, &first);
  578. if(retval != UA_STATUSCODE_GOOD)
  579. return retval;
  580. /* Allocate the array */
  581. UA_Variant_init(dst);
  582. dst->data = UA_Array_new(count, src->type);
  583. if(!dst->data)
  584. return UA_STATUSCODE_BADOUTOFMEMORY;
  585. /* Copy the range */
  586. size_t block_count = count / block;
  587. size_t elem_size = src->type->memSize;
  588. uintptr_t nextdst = (uintptr_t)dst->data;
  589. uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
  590. if(nextrange.dimensionsSize == 0) {
  591. /* no nextrange */
  592. if(src->type->pointerFree) {
  593. for(size_t i = 0; i < block_count; ++i) {
  594. memcpy((void*)nextdst, (void*)nextsrc, elem_size * block);
  595. nextdst += block * elem_size;
  596. nextsrc += stride * elem_size;
  597. }
  598. } else {
  599. for(size_t i = 0; i < block_count; ++i) {
  600. for(size_t j = 0; j < block; ++j) {
  601. retval = UA_copy((const void*)nextsrc,
  602. (void*)nextdst, src->type);
  603. nextdst += elem_size;
  604. nextsrc += elem_size;
  605. }
  606. nextsrc += (stride - block) * elem_size;
  607. }
  608. }
  609. } else {
  610. /* nextrange can only be used for variants and stringlike with remaining
  611. * range of dimension 1 */
  612. if(src->type != &UA_TYPES[UA_TYPES_VARIANT]) {
  613. if(!stringLike)
  614. retval = UA_STATUSCODE_BADINDEXRANGENODATA;
  615. if(nextrange.dimensionsSize != 1)
  616. retval = UA_STATUSCODE_BADINDEXRANGENODATA;
  617. }
  618. /* Copy the content */
  619. for(size_t i = 0; i < block_count; ++i) {
  620. for(size_t j = 0; j < block && retval == UA_STATUSCODE_GOOD; ++j) {
  621. if(stringLike)
  622. retval = copySubString((const UA_String*)nextsrc,
  623. (UA_String*)nextdst,
  624. nextrange.dimensions);
  625. else
  626. retval = UA_Variant_copyRange((const UA_Variant*)nextsrc,
  627. (UA_Variant*)nextdst,
  628. nextrange);
  629. nextdst += elem_size;
  630. nextsrc += elem_size;
  631. }
  632. nextsrc += (stride - block) * elem_size;
  633. }
  634. }
  635. /* Clean up if copying failed */
  636. if(retval != UA_STATUSCODE_GOOD) {
  637. UA_Array_delete(dst->data, count, src->type);
  638. dst->data = NULL;
  639. return retval;
  640. }
  641. /* Done if scalar */
  642. dst->type = src->type;
  643. if(isScalar)
  644. return retval;
  645. /* Copy array dimensions */
  646. dst->arrayLength = count;
  647. if(src->arrayDimensionsSize > 0) {
  648. dst->arrayDimensions =
  649. (u32*)UA_Array_new(thisrange.dimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
  650. if(!dst->arrayDimensions) {
  651. Variant_clear(dst, NULL);
  652. return UA_STATUSCODE_BADOUTOFMEMORY;
  653. }
  654. dst->arrayDimensionsSize = thisrange.dimensionsSize;
  655. for(size_t k = 0; k < thisrange.dimensionsSize; ++k)
  656. dst->arrayDimensions[k] =
  657. thisrange.dimensions[k].max - thisrange.dimensions[k].min + 1;
  658. }
  659. return UA_STATUSCODE_GOOD;
  660. }
  661. /* TODO: Allow ranges to reach inside a scalars that are array-like, e.g.
  662. * variant and strings. This is already possible for reading... */
  663. static UA_StatusCode
  664. Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
  665. const UA_NumericRange range, UA_Boolean copy) {
  666. /* Compute the strides */
  667. size_t count, block, stride, first;
  668. UA_StatusCode retval = computeStrides(v, range, &count,
  669. &block, &stride, &first);
  670. if(retval != UA_STATUSCODE_GOOD)
  671. return retval;
  672. if(count != arraySize)
  673. return UA_STATUSCODE_BADINDEXRANGEINVALID;
  674. /* Move/copy the elements */
  675. size_t block_count = count / block;
  676. size_t elem_size = v->type->memSize;
  677. uintptr_t nextdst = (uintptr_t)v->data + (first * elem_size);
  678. uintptr_t nextsrc = (uintptr_t)array;
  679. if(v->type->pointerFree || !copy) {
  680. for(size_t i = 0; i < block_count; ++i) {
  681. memcpy((void*)nextdst, (void*)nextsrc, elem_size * block);
  682. nextsrc += block * elem_size;
  683. nextdst += stride * elem_size;
  684. }
  685. } else {
  686. for(size_t i = 0; i < block_count; ++i) {
  687. for(size_t j = 0; j < block; ++j) {
  688. clear_noInit((void*)nextdst, v->type);
  689. retval |= UA_copy((void*)nextsrc, (void*)nextdst, v->type);
  690. nextdst += elem_size;
  691. nextsrc += elem_size;
  692. }
  693. nextdst += (stride - block) * elem_size;
  694. }
  695. }
  696. /* If members were moved, initialize original array to prevent reuse */
  697. if(!copy && !v->type->pointerFree)
  698. memset(array, 0, sizeof(elem_size)*arraySize);
  699. return retval;
  700. }
  701. UA_StatusCode
  702. UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
  703. size_t arraySize, const UA_NumericRange range) {
  704. return Variant_setRange(v, array, arraySize, range, false);
  705. }
  706. UA_StatusCode
  707. UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
  708. size_t arraySize, const UA_NumericRange range) {
  709. return Variant_setRange(v, (void*)(uintptr_t)array,
  710. arraySize, range, true);
  711. }
  712. /* LocalizedText */
  713. static void
  714. LocalizedText_clear(UA_LocalizedText *p, const UA_DataType *_) {
  715. String_clear(&p->locale, NULL);
  716. String_clear(&p->text, NULL);
  717. }
  718. static UA_StatusCode
  719. LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst,
  720. const UA_DataType *_) {
  721. UA_StatusCode retval = UA_String_copy(&src->locale, &dst->locale);
  722. retval |= UA_String_copy(&src->text, &dst->text);
  723. return retval;
  724. }
  725. /* DataValue */
  726. static void
  727. DataValue_clear(UA_DataValue *p, const UA_DataType *_) {
  728. Variant_clear(&p->value, NULL);
  729. }
  730. static UA_StatusCode
  731. DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
  732. const UA_DataType *_) {
  733. memcpy(dst, src, sizeof(UA_DataValue));
  734. UA_Variant_init(&dst->value);
  735. UA_StatusCode retval = Variant_copy(&src->value, &dst->value, NULL);
  736. if(retval != UA_STATUSCODE_GOOD)
  737. DataValue_clear(dst, NULL);
  738. return retval;
  739. }
  740. /* DiagnosticInfo */
  741. static void
  742. DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) {
  743. String_clear(&p->additionalInfo, NULL);
  744. if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
  745. DiagnosticInfo_clear(p->innerDiagnosticInfo, NULL);
  746. UA_free(p->innerDiagnosticInfo);
  747. }
  748. }
  749. static UA_StatusCode
  750. DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
  751. const UA_DataType *_) {
  752. memcpy(dst, src, sizeof(UA_DiagnosticInfo));
  753. UA_String_init(&dst->additionalInfo);
  754. dst->innerDiagnosticInfo = NULL;
  755. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  756. if(src->hasAdditionalInfo)
  757. retval = UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
  758. if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
  759. dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)UA_malloc(sizeof(UA_DiagnosticInfo));
  760. if(dst->innerDiagnosticInfo) {
  761. retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo,
  762. dst->innerDiagnosticInfo, NULL);
  763. dst->hasInnerDiagnosticInfo = true;
  764. } else {
  765. dst->hasInnerDiagnosticInfo = false;
  766. retval |= UA_STATUSCODE_BADOUTOFMEMORY;
  767. }
  768. }
  769. return retval;
  770. }
  771. /********************/
  772. /* Structured Types */
  773. /********************/
  774. void *
  775. UA_new(const UA_DataType *type) {
  776. void *p = UA_calloc(1, type->memSize);
  777. return p;
  778. }
  779. static UA_StatusCode
  780. copyByte(const u8 *src, u8 *dst, const UA_DataType *_) {
  781. *dst = *src;
  782. return UA_STATUSCODE_GOOD;
  783. }
  784. static UA_StatusCode
  785. copy2Byte(const u16 *src, u16 *dst, const UA_DataType *_) {
  786. *dst = *src;
  787. return UA_STATUSCODE_GOOD;
  788. }
  789. static UA_StatusCode
  790. copy4Byte(const u32 *src, u32 *dst, const UA_DataType *_) {
  791. *dst = *src;
  792. return UA_STATUSCODE_GOOD;
  793. }
  794. static UA_StatusCode
  795. copy8Byte(const u64 *src, u64 *dst, const UA_DataType *_) {
  796. *dst = *src;
  797. return UA_STATUSCODE_GOOD;
  798. }
  799. static UA_StatusCode
  800. copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
  801. *dst = *src;
  802. return UA_STATUSCODE_GOOD;
  803. }
  804. typedef UA_StatusCode
  805. (*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
  806. static const UA_copySignature copyJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  807. (UA_copySignature)copyByte, // Boolean
  808. (UA_copySignature)copyByte, // SByte
  809. (UA_copySignature)copyByte, // Byte
  810. (UA_copySignature)copy2Byte, // Int16
  811. (UA_copySignature)copy2Byte, // UInt16
  812. (UA_copySignature)copy4Byte, // Int32
  813. (UA_copySignature)copy4Byte, // UInt32
  814. (UA_copySignature)copy8Byte, // Int64
  815. (UA_copySignature)copy8Byte, // UInt64
  816. (UA_copySignature)copy4Byte, // Float
  817. (UA_copySignature)copy8Byte, // Double
  818. (UA_copySignature)String_copy,
  819. (UA_copySignature)copy8Byte, // DateTime
  820. (UA_copySignature)copyGuid, // Guid
  821. (UA_copySignature)String_copy, // ByteString
  822. (UA_copySignature)String_copy, // XmlElement
  823. (UA_copySignature)NodeId_copy,
  824. (UA_copySignature)ExpandedNodeId_copy,
  825. (UA_copySignature)copy4Byte, // StatusCode
  826. (UA_copySignature)QualifiedName_copy,
  827. (UA_copySignature)LocalizedText_copy,
  828. (UA_copySignature)ExtensionObject_copy,
  829. (UA_copySignature)DataValue_copy,
  830. (UA_copySignature)Variant_copy,
  831. (UA_copySignature)DiagnosticInfo_copy,
  832. (UA_copySignature)copy_noInit // all others
  833. };
  834. static UA_StatusCode
  835. copy_noInit(const void *src, void *dst, const UA_DataType *type) {
  836. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  837. uintptr_t ptrs = (uintptr_t)src;
  838. uintptr_t ptrd = (uintptr_t)dst;
  839. u8 membersSize = type->membersSize;
  840. for(size_t i = 0; i < membersSize; ++i) {
  841. const UA_DataTypeMember *m= &type->members[i];
  842. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  843. const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
  844. if(!m->isArray) {
  845. ptrs += m->padding;
  846. ptrd += m->padding;
  847. size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
  848. retval |= copyJumpTable[fi]((const void*)ptrs, (void*)ptrd, mt);
  849. ptrs += mt->memSize;
  850. ptrd += mt->memSize;
  851. } else {
  852. ptrs += m->padding;
  853. ptrd += m->padding;
  854. size_t *dst_size = (size_t*)ptrd;
  855. const size_t size = *((const size_t*)ptrs);
  856. ptrs += sizeof(size_t);
  857. ptrd += sizeof(size_t);
  858. retval |= UA_Array_copy(*(void* const*)ptrs, size, (void**)ptrd, mt);
  859. if(retval == UA_STATUSCODE_GOOD)
  860. *dst_size = size;
  861. else
  862. *dst_size = 0;
  863. ptrs += sizeof(void*);
  864. ptrd += sizeof(void*);
  865. }
  866. }
  867. return retval;
  868. }
  869. UA_StatusCode
  870. UA_copy(const void *src, void *dst, const UA_DataType *type) {
  871. memset(dst, 0, type->memSize); /* init */
  872. UA_StatusCode retval = copy_noInit(src, dst, type);
  873. if(retval != UA_STATUSCODE_GOOD)
  874. UA_clear(dst, type);
  875. return retval;
  876. }
  877. static void nopClear(void *p, const UA_DataType *type) { }
  878. typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);
  879. static const
  880. UA_clearSignature clearJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  881. (UA_clearSignature)nopClear, // Boolean
  882. (UA_clearSignature)nopClear, // SByte
  883. (UA_clearSignature)nopClear, // Byte
  884. (UA_clearSignature)nopClear, // Int16
  885. (UA_clearSignature)nopClear, // UInt16
  886. (UA_clearSignature)nopClear, // Int32
  887. (UA_clearSignature)nopClear, // UInt32
  888. (UA_clearSignature)nopClear, // Int64
  889. (UA_clearSignature)nopClear, // UInt64
  890. (UA_clearSignature)nopClear, // Float
  891. (UA_clearSignature)nopClear, // Double
  892. (UA_clearSignature)String_clear, // String
  893. (UA_clearSignature)nopClear, // DateTime
  894. (UA_clearSignature)nopClear, // Guid
  895. (UA_clearSignature)String_clear, // ByteString
  896. (UA_clearSignature)String_clear, // XmlElement
  897. (UA_clearSignature)NodeId_clear,
  898. (UA_clearSignature)ExpandedNodeId_clear,
  899. (UA_clearSignature)nopClear, // StatusCode
  900. (UA_clearSignature)QualifiedName_clear,
  901. (UA_clearSignature)LocalizedText_clear,
  902. (UA_clearSignature)ExtensionObject_clear,
  903. (UA_clearSignature)DataValue_clear,
  904. (UA_clearSignature)Variant_clear,
  905. (UA_clearSignature)DiagnosticInfo_clear,
  906. (UA_clearSignature)clear_noInit,
  907. };
  908. static void
  909. clear_noInit(void *p, const UA_DataType *type) {
  910. uintptr_t ptr = (uintptr_t)p;
  911. u8 membersSize = type->membersSize;
  912. for(size_t i = 0; i < membersSize; ++i) {
  913. const UA_DataTypeMember *m= &type->members[i];
  914. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  915. const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
  916. if(!m->isArray) {
  917. ptr += m->padding;
  918. size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
  919. clearJumpTable[fi]((void*)ptr, mt);
  920. ptr += mt->memSize;
  921. } else {
  922. ptr += m->padding;
  923. size_t length = *(size_t*)ptr;
  924. ptr += sizeof(size_t);
  925. UA_Array_delete(*(void**)ptr, length, mt);
  926. ptr += sizeof(void*);
  927. }
  928. }
  929. }
  930. void
  931. UA_clear(void *p, const UA_DataType *type) {
  932. clear_noInit(p, type);
  933. memset(p, 0, type->memSize); /* init */
  934. }
  935. void
  936. UA_delete(void *p, const UA_DataType *type) {
  937. clear_noInit(p, type);
  938. UA_free(p);
  939. }
  940. /******************/
  941. /* Array Handling */
  942. /******************/
  943. void *
  944. UA_Array_new(size_t size, const UA_DataType *type) {
  945. if(size > UA_INT32_MAX)
  946. return NULL;
  947. if(size == 0)
  948. return UA_EMPTY_ARRAY_SENTINEL;
  949. return UA_calloc(size, type->memSize);
  950. }
  951. UA_StatusCode
  952. UA_Array_copy(const void *src, size_t size,
  953. void **dst, const UA_DataType *type) {
  954. if(size == 0) {
  955. if(src == NULL)
  956. *dst = NULL;
  957. else
  958. *dst= UA_EMPTY_ARRAY_SENTINEL;
  959. return UA_STATUSCODE_GOOD;
  960. }
  961. if(!type)
  962. return UA_STATUSCODE_BADINTERNALERROR;
  963. /* calloc, so we don't have to check retval in every iteration of copying */
  964. *dst = UA_calloc(size, type->memSize);
  965. if(!*dst)
  966. return UA_STATUSCODE_BADOUTOFMEMORY;
  967. if(type->pointerFree) {
  968. memcpy(*dst, src, type->memSize * size);
  969. return UA_STATUSCODE_GOOD;
  970. }
  971. uintptr_t ptrs = (uintptr_t)src;
  972. uintptr_t ptrd = (uintptr_t)*dst;
  973. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  974. for(size_t i = 0; i < size; ++i) {
  975. retval |= UA_copy((void*)ptrs, (void*)ptrd, type);
  976. ptrs += type->memSize;
  977. ptrd += type->memSize;
  978. }
  979. if(retval != UA_STATUSCODE_GOOD) {
  980. UA_Array_delete(*dst, size, type);
  981. *dst = NULL;
  982. }
  983. return retval;
  984. }
  985. void
  986. UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
  987. if(!type->pointerFree) {
  988. uintptr_t ptr = (uintptr_t)p;
  989. for(size_t i = 0; i < size; ++i) {
  990. UA_clear((void*)ptr, type);
  991. ptr += type->memSize;
  992. }
  993. }
  994. UA_free((void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
  995. }
  996. UA_Boolean
  997. UA_DataType_isNumeric(const UA_DataType *type) {
  998. /* All data types between UA_TYPES_BOOLEAN and UA_TYPES_DOUBLE are numeric */
  999. for(size_t i = UA_TYPES_BOOLEAN; i <= UA_TYPES_DOUBLE; ++i)
  1000. if(&UA_TYPES[i] == type)
  1001. return true;
  1002. return false;
  1003. }
  1004. /**********************/
  1005. /* Parse NumericRange */
  1006. /**********************/
  1007. static size_t
  1008. readDimension(UA_Byte *buf, size_t buflen, UA_NumericRangeDimension *dim) {
  1009. size_t progress = UA_readNumber(buf, buflen, &dim->min);
  1010. if(progress == 0)
  1011. return 0;
  1012. if(buflen <= progress + 1 || buf[progress] != ':') {
  1013. dim->max = dim->min;
  1014. return progress;
  1015. }
  1016. ++progress;
  1017. size_t progress2 = UA_readNumber(&buf[progress], buflen - progress, &dim->max);
  1018. if(progress2 == 0)
  1019. return 0;
  1020. /* invalid range */
  1021. if(dim->min >= dim->max)
  1022. return 0;
  1023. return progress + progress2;
  1024. }
  1025. UA_StatusCode
  1026. UA_NumericRange_parseFromString(UA_NumericRange *range, const UA_String *str) {
  1027. size_t idx = 0;
  1028. size_t dimensionsMax = 0;
  1029. UA_NumericRangeDimension *dimensions = NULL;
  1030. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1031. size_t offset = 0;
  1032. while(true) {
  1033. /* alloc dimensions */
  1034. if(idx >= dimensionsMax) {
  1035. UA_NumericRangeDimension *newds;
  1036. size_t newdssize = sizeof(UA_NumericRangeDimension) * (dimensionsMax + 2);
  1037. newds = (UA_NumericRangeDimension*)UA_realloc(dimensions, newdssize);
  1038. if(!newds) {
  1039. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  1040. break;
  1041. }
  1042. dimensions = newds;
  1043. dimensionsMax = dimensionsMax + 2;
  1044. }
  1045. /* read the dimension */
  1046. size_t progress = readDimension(&str->data[offset], str->length - offset,
  1047. &dimensions[idx]);
  1048. if(progress == 0) {
  1049. retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
  1050. break;
  1051. }
  1052. offset += progress;
  1053. ++idx;
  1054. /* loop into the next dimension */
  1055. if(offset >= str->length)
  1056. break;
  1057. if(str->data[offset] != ',') {
  1058. retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
  1059. break;
  1060. }
  1061. ++offset;
  1062. }
  1063. if(retval == UA_STATUSCODE_GOOD && idx > 0) {
  1064. range->dimensions = dimensions;
  1065. range->dimensionsSize = idx;
  1066. } else
  1067. UA_free(dimensions);
  1068. return retval;
  1069. }