ua_types_encoding_binary.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570
  1. #include "ua_util.h"
  2. #include "ua_types_encoding_binary.h"
  3. #include "ua_types_generated.h"
  4. #include "ua_types_generated_handling.h"
  5. /* Type Encoding
  6. * -------------
  7. * This file contains encoding functions for the builtin data types and generic
  8. * functions that operate on all types and arrays. This requires the type
  9. * description from a UA_DataType structure. Note that some internal (static)
  10. * deocidng functions may abort and leave the type in an inconsistent state. But
  11. * this is always handled in UA_decodeBinary, where the error is caught and the
  12. * type cleaned up.
  13. *
  14. * Breaking a message into chunks is integrated with the encoding. When the end
  15. * of a buffer is reached, a callback is executed that sends the current buffer
  16. * as a chunk and exchanges the encoding buffer "underneath" the ongoing
  17. * encoding. This enables fast sending of large messages as spurious copying is
  18. * avoided. */
  19. /* There is no robust way to detect float endianness in clang. This warning can
  20. * be removed if the target is known to be little endian with floats in the IEEE
  21. * 754 format. */
  22. #if defined(__clang__)
  23. # pragma GCC diagnostic push
  24. # pragma GCC diagnostic warning "-W#warnings"
  25. #endif
  26. #ifndef UA_BINARY_OVERLAYABLE_INTEGER
  27. # warning Integer endianness could not be detected to be little endian. Use slow generic encoding.
  28. #endif
  29. #ifndef UA_BINARY_OVERLAYABLE_FLOAT
  30. # warning Float endianness could not be detected to be little endian in the IEEE 754 format. Use slow generic encoding.
  31. #endif
  32. #if defined(__clang__)
  33. # pragma GCC diagnostic pop
  34. #endif
  35. /* Jumptables for de-/encoding and computing the buffer length */
  36. typedef UA_StatusCode (*UA_encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type);
  37. static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  38. typedef UA_StatusCode (*UA_decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type);
  39. static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  40. typedef size_t (*UA_calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
  41. static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  42. /* We give pointers to the current position and the last position in the buffer
  43. instead of a string with an offset. */
  44. UA_THREAD_LOCAL UA_Byte * pos;
  45. UA_THREAD_LOCAL UA_Byte * end;
  46. /* The code UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED is returned only when the
  47. * end of the buffer is reached. This error is caught. We then try to send the
  48. * current chunk and continue with the next. */
  49. /* Thread-local buffers used for exchanging the buffer for chunking */
  50. UA_THREAD_LOCAL UA_ByteString *encodeBuf; /* the original buffer */
  51. UA_THREAD_LOCAL UA_exchangeEncodeBuffer exchangeBufferCallback;
  52. UA_THREAD_LOCAL void *exchangeBufferCallbackHandle;
  53. /* Send the current chunk and replace the buffer */
  54. static UA_StatusCode
  55. exchangeBuffer(void) {
  56. if(!exchangeBufferCallback)
  57. return UA_STATUSCODE_BADENCODINGERROR;
  58. /* store context variables since chunk-sending might call UA_encode itself */
  59. UA_ByteString *store_encodeBuf = encodeBuf;
  60. UA_exchangeEncodeBuffer store_exchangeBufferCallback = exchangeBufferCallback;
  61. void *store_exchangeBufferCallbackHandle = exchangeBufferCallbackHandle;
  62. size_t offset = ((uintptr_t)pos - (uintptr_t)encodeBuf->data) / sizeof(UA_Byte);
  63. UA_StatusCode retval = exchangeBufferCallback(exchangeBufferCallbackHandle, encodeBuf, offset);
  64. /* restore context variables */
  65. encodeBuf = store_encodeBuf;
  66. exchangeBufferCallback = store_exchangeBufferCallback;
  67. exchangeBufferCallbackHandle = store_exchangeBufferCallbackHandle;
  68. /* set pos and end in order to continue encoding */
  69. pos = encodeBuf->data;
  70. end = &encodeBuf->data[encodeBuf->length];
  71. return retval;
  72. }
  73. /*****************/
  74. /* Integer Types */
  75. /*****************/
  76. /* The following en/decoding functions are used only when the architecture isn't
  77. little-endian. */
  78. static void
  79. UA_encode16(const UA_UInt16 v, UA_Byte buf[2]) {
  80. buf[0] = (UA_Byte)v;
  81. buf[1] = (UA_Byte)(v >> 8);
  82. }
  83. static void
  84. UA_decode16(const UA_Byte buf[2], UA_UInt16 *v) {
  85. *v = (UA_UInt16)((UA_UInt16)buf[0] + (((UA_UInt16)buf[1]) << 8));
  86. }
  87. static void
  88. UA_encode32(const UA_UInt32 v, UA_Byte buf[4]) {
  89. buf[0] = (UA_Byte)v;
  90. buf[1] = (UA_Byte)(v >> 8);
  91. buf[2] = (UA_Byte)(v >> 16);
  92. buf[3] = (UA_Byte)(v >> 24);
  93. }
  94. static void
  95. UA_decode32(const UA_Byte buf[4], UA_UInt32 *v) {
  96. *v = (UA_UInt32)((UA_UInt32)buf[0] +
  97. (((UA_UInt32)buf[1]) << 8) +
  98. (((UA_UInt32)buf[2]) << 16) +
  99. (((UA_UInt32)buf[3]) << 24));
  100. }
  101. static void
  102. UA_encode64(const UA_UInt64 v, UA_Byte buf[8]) {
  103. buf[0] = (UA_Byte)v;
  104. buf[1] = (UA_Byte)(v >> 8);
  105. buf[2] = (UA_Byte)(v >> 16);
  106. buf[3] = (UA_Byte)(v >> 24);
  107. buf[4] = (UA_Byte)(v >> 32);
  108. buf[5] = (UA_Byte)(v >> 40);
  109. buf[6] = (UA_Byte)(v >> 48);
  110. buf[7] = (UA_Byte)(v >> 56);
  111. }
  112. static void
  113. UA_decode64(const UA_Byte buf[8], UA_UInt64 *v) {
  114. *v = (UA_UInt64)((UA_UInt64)buf[0] +
  115. (((UA_UInt64)buf[1]) << 8) +
  116. (((UA_UInt64)buf[2]) << 16) +
  117. (((UA_UInt64)buf[3]) << 24) +
  118. (((UA_UInt64)buf[4]) << 32) +
  119. (((UA_UInt64)buf[5]) << 40) +
  120. (((UA_UInt64)buf[6]) << 48) +
  121. (((UA_UInt64)buf[7]) << 56));
  122. }
  123. /* Boolean */
  124. static UA_StatusCode
  125. Boolean_encodeBinary(const UA_Boolean *src, const UA_DataType *_) {
  126. if(pos + sizeof(UA_Boolean) > end)
  127. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  128. *pos = *(const UA_Byte*)src;
  129. ++pos;
  130. return UA_STATUSCODE_GOOD;
  131. }
  132. static UA_StatusCode
  133. Boolean_decodeBinary(UA_Boolean *dst, const UA_DataType *_) {
  134. if(pos + sizeof(UA_Boolean) > end)
  135. return UA_STATUSCODE_BADDECODINGERROR;
  136. *dst = (*pos > 0) ? true : false;
  137. ++pos;
  138. return UA_STATUSCODE_GOOD;
  139. }
  140. /* Byte */
  141. static UA_StatusCode
  142. Byte_encodeBinary(const UA_Byte *src, const UA_DataType *_) {
  143. if(pos + sizeof(UA_Byte) > end)
  144. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  145. *pos = *(const UA_Byte*)src;
  146. ++pos;
  147. return UA_STATUSCODE_GOOD;
  148. }
  149. static UA_StatusCode
  150. Byte_decodeBinary(UA_Byte *dst, const UA_DataType *_) {
  151. if(pos + sizeof(UA_Byte) > end)
  152. return UA_STATUSCODE_BADDECODINGERROR;
  153. *dst = *pos;
  154. ++pos;
  155. return UA_STATUSCODE_GOOD;
  156. }
  157. /* UInt16 */
  158. static UA_StatusCode
  159. UInt16_encodeBinary(UA_UInt16 const *src, const UA_DataType *_) {
  160. if(pos + sizeof(UA_UInt16) > end)
  161. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  162. #if UA_BINARY_OVERLAYABLE_INTEGER
  163. memcpy(pos, src, sizeof(UA_UInt16));
  164. #else
  165. UA_encode16(*src, pos);
  166. #endif
  167. pos += 2;
  168. return UA_STATUSCODE_GOOD;
  169. }
  170. static UA_INLINE UA_StatusCode
  171. Int16_encodeBinary(UA_Int16 const *src, const UA_DataType *_) {
  172. return UInt16_encodeBinary((const UA_UInt16*)src, NULL);
  173. }
  174. static UA_StatusCode
  175. UInt16_decodeBinary(UA_UInt16 *dst, const UA_DataType *_) {
  176. if(pos + sizeof(UA_UInt16) > end)
  177. return UA_STATUSCODE_BADDECODINGERROR;
  178. #if UA_BINARY_OVERLAYABLE_INTEGER
  179. memcpy(dst, pos, sizeof(UA_UInt16));
  180. #else
  181. UA_decode16(pos, dst);
  182. #endif
  183. pos += 2;
  184. return UA_STATUSCODE_GOOD;
  185. }
  186. static UA_INLINE UA_StatusCode
  187. Int16_decodeBinary(UA_Int16 *dst) {
  188. return UInt16_decodeBinary((UA_UInt16*)dst, NULL);
  189. }
  190. /* UInt32 */
  191. static UA_StatusCode
  192. UInt32_encodeBinary(UA_UInt32 const *src, const UA_DataType *_) {
  193. if(pos + sizeof(UA_UInt32) > end)
  194. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  195. #if UA_BINARY_OVERLAYABLE_INTEGER
  196. memcpy(pos, src, sizeof(UA_UInt32));
  197. #else
  198. UA_encode32(*src, pos);
  199. #endif
  200. pos += 4;
  201. return UA_STATUSCODE_GOOD;
  202. }
  203. static UA_INLINE UA_StatusCode
  204. Int32_encodeBinary(UA_Int32 const *src) {
  205. return UInt32_encodeBinary((const UA_UInt32*)src, NULL);
  206. }
  207. static UA_INLINE UA_StatusCode
  208. StatusCode_encodeBinary(UA_StatusCode const *src) {
  209. return UInt32_encodeBinary((const UA_UInt32*)src, NULL);
  210. }
  211. static UA_StatusCode
  212. UInt32_decodeBinary(UA_UInt32 *dst, const UA_DataType *_) {
  213. if(pos + sizeof(UA_UInt32) > end)
  214. return UA_STATUSCODE_BADDECODINGERROR;
  215. #if UA_BINARY_OVERLAYABLE_INTEGER
  216. memcpy(dst, pos, sizeof(UA_UInt32));
  217. #else
  218. UA_decode32(pos, dst);
  219. #endif
  220. pos += 4;
  221. return UA_STATUSCODE_GOOD;
  222. }
  223. static UA_INLINE UA_StatusCode
  224. Int32_decodeBinary(UA_Int32 *dst) {
  225. return UInt32_decodeBinary((UA_UInt32*)dst, NULL);
  226. }
  227. static UA_INLINE UA_StatusCode
  228. StatusCode_decodeBinary(UA_StatusCode *dst) {
  229. return UInt32_decodeBinary((UA_UInt32*)dst, NULL);
  230. }
  231. /* UInt64 */
  232. static UA_StatusCode
  233. UInt64_encodeBinary(UA_UInt64 const *src, const UA_DataType *_) {
  234. if(pos + sizeof(UA_UInt64) > end)
  235. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  236. #if UA_BINARY_OVERLAYABLE_INTEGER
  237. memcpy(pos, src, sizeof(UA_UInt64));
  238. #else
  239. UA_encode64(*src, pos);
  240. #endif
  241. pos += 8;
  242. return UA_STATUSCODE_GOOD;
  243. }
  244. static UA_INLINE UA_StatusCode
  245. Int64_encodeBinary(UA_Int64 const *src) {
  246. return UInt64_encodeBinary((const UA_UInt64*)src, NULL);
  247. }
  248. static UA_INLINE UA_StatusCode
  249. DateTime_encodeBinary(UA_DateTime const *src) {
  250. return UInt64_encodeBinary((const UA_UInt64*)src, NULL);
  251. }
  252. static UA_StatusCode
  253. UInt64_decodeBinary(UA_UInt64 *dst, const UA_DataType *_) {
  254. if(pos + sizeof(UA_UInt64) > end)
  255. return UA_STATUSCODE_BADDECODINGERROR;
  256. #if UA_BINARY_OVERLAYABLE_INTEGER
  257. memcpy(dst, pos, sizeof(UA_UInt64));
  258. #else
  259. UA_decode64(pos, dst);
  260. #endif
  261. pos += 8;
  262. return UA_STATUSCODE_GOOD;
  263. }
  264. static UA_INLINE UA_StatusCode
  265. Int64_decodeBinary(UA_Int64 *dst) {
  266. return UInt64_decodeBinary((UA_UInt64*)dst, NULL);
  267. }
  268. static UA_INLINE UA_StatusCode
  269. DateTime_decodeBinary(UA_DateTime *dst) {
  270. return UInt64_decodeBinary((UA_UInt64*)dst, NULL);
  271. }
  272. /************************/
  273. /* Floating Point Types */
  274. /************************/
  275. #if UA_BINARY_OVERLAYABLE_FLOAT
  276. # define Float_encodeBinary UInt32_encodeBinary
  277. # define Float_decodeBinary UInt32_decodeBinary
  278. # define Double_encodeBinary UInt64_encodeBinary
  279. # define Double_decodeBinary UInt64_decodeBinary
  280. #else
  281. #include <math.h>
  282. /* Handling of IEEE754 floating point values was taken from Beej's Guide to
  283. * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
  284. * edge cases +/-0, +/-inf and nan. */
  285. static uint64_t
  286. pack754(long double f, unsigned bits, unsigned expbits) {
  287. unsigned significandbits = bits - expbits - 1;
  288. long double fnorm;
  289. long long sign;
  290. if (f < 0) { sign = 1; fnorm = -f; }
  291. else { sign = 0; fnorm = f; }
  292. int shift = 0;
  293. while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
  294. while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
  295. fnorm = fnorm - 1.0;
  296. long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
  297. long long exponent = shift + ((1<<(expbits-1)) - 1);
  298. return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
  299. }
  300. static long double
  301. unpack754(uint64_t i, unsigned bits, unsigned expbits) {
  302. unsigned significandbits = bits - expbits - 1;
  303. long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
  304. result /= (1LL<<significandbits);
  305. result += 1.0f;
  306. unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
  307. long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
  308. while(shift > 0) { result *= 2.0; --shift; }
  309. while(shift < 0) { result /= 2.0; ++shift; }
  310. result *= ((i>>(bits-1))&1)? -1.0: 1.0;
  311. return result;
  312. }
  313. /* Float */
  314. #define FLOAT_NAN 0xffc00000
  315. #define FLOAT_INF 0x7f800000
  316. #define FLOAT_NEG_INF 0xff800000
  317. #define FLOAT_NEG_ZERO 0x80000000
  318. static UA_StatusCode
  319. Float_encodeBinary(UA_Float const *src, const UA_DataType *_) {
  320. UA_Float f = *src;
  321. UA_UInt32 encoded;
  322. //cppcheck-suppress duplicateExpression
  323. if(f != f) encoded = FLOAT_NAN;
  324. else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
  325. //cppcheck-suppress duplicateExpression
  326. else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
  327. else encoded = (UA_UInt32)pack754(f, 32, 8);
  328. return UInt32_encodeBinary(&encoded, NULL);
  329. }
  330. static UA_StatusCode
  331. Float_decodeBinary(UA_Float *dst, const UA_DataType *_) {
  332. UA_UInt32 decoded;
  333. UA_StatusCode retval = UInt32_decodeBinary(&decoded, NULL);
  334. if(retval != UA_STATUSCODE_GOOD)
  335. return retval;
  336. if(decoded == 0) *dst = 0.0f;
  337. else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
  338. else if(decoded == FLOAT_INF) *dst = INFINITY;
  339. else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
  340. if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
  341. (decoded >= 0xff800001 && decoded <= 0xffffffff)) *dst = NAN;
  342. else *dst = (UA_Float)unpack754(decoded, 32, 8);
  343. return UA_STATUSCODE_GOOD;
  344. }
  345. /* Double */
  346. #define DOUBLE_NAN 0xfff8000000000000L
  347. #define DOUBLE_INF 0x7ff0000000000000L
  348. #define DOUBLE_NEG_INF 0xfff0000000000000L
  349. #define DOUBLE_NEG_ZERO 0x8000000000000000L
  350. static UA_StatusCode
  351. Double_encodeBinary(UA_Double const *src, const UA_DataType *_) {
  352. UA_Double d = *src;
  353. UA_UInt64 encoded;
  354. //cppcheck-suppress duplicateExpression
  355. if(d != d) encoded = DOUBLE_NAN;
  356. else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
  357. //cppcheck-suppress duplicateExpression
  358. else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
  359. else encoded = pack754(d, 64, 11);
  360. return UInt64_encodeBinary(&encoded, NULL);
  361. }
  362. static UA_StatusCode
  363. Double_decodeBinary(UA_Double *dst, const UA_DataType *_) {
  364. UA_UInt64 decoded;
  365. UA_StatusCode retval = UInt64_decodeBinary(&decoded, NULL);
  366. if(retval != UA_STATUSCODE_GOOD)
  367. return retval;
  368. if(decoded == 0) *dst = 0.0;
  369. else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
  370. else if(decoded == DOUBLE_INF) *dst = INFINITY;
  371. else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
  372. //cppcheck-suppress redundantCondition
  373. if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
  374. (decoded >= 0xfff0000000000001L && decoded <= 0xffffffffffffffffL)) *dst = NAN;
  375. else *dst = (UA_Double)unpack754(decoded, 64, 11);
  376. return UA_STATUSCODE_GOOD;
  377. }
  378. #endif
  379. /******************/
  380. /* Array Handling */
  381. /******************/
  382. static UA_StatusCode
  383. Array_encodeBinary(const void *src, size_t length, const UA_DataType *type) {
  384. UA_Int32 signed_length = -1;
  385. if(length > UA_INT32_MAX)
  386. return UA_STATUSCODE_BADINTERNALERROR;
  387. if(length > 0)
  388. signed_length = (UA_Int32)length;
  389. else if(src == UA_EMPTY_ARRAY_SENTINEL)
  390. signed_length = 0;
  391. UA_StatusCode retval = Int32_encodeBinary(&signed_length);
  392. if(retval != UA_STATUSCODE_GOOD || length == 0)
  393. return retval;
  394. if(type->overlayable) {
  395. size_t i = 0; /* the number of already encoded elements */
  396. while(end < pos + (type->memSize * (length-i))) {
  397. /* not enough space, need to exchange the buffer */
  398. size_t elements = ((uintptr_t)end - (uintptr_t)pos) / (sizeof(UA_Byte) * type->memSize);
  399. memcpy(pos, src, type->memSize * elements);
  400. pos += type->memSize * elements;
  401. i += elements;
  402. retval = exchangeBuffer();
  403. if(retval != UA_STATUSCODE_GOOD)
  404. return retval;
  405. }
  406. /* encode the remaining elements */
  407. memcpy(pos, src, type->memSize * (length-i));
  408. pos += type->memSize * (length-i);
  409. return UA_STATUSCODE_GOOD;
  410. }
  411. uintptr_t ptr = (uintptr_t)src;
  412. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  413. for(size_t i = 0; i < length && retval == UA_STATUSCODE_GOOD; ++i) {
  414. UA_Byte *oldpos = pos;
  415. retval = encodeBinaryJumpTable[encode_index]((const void*)ptr, type);
  416. ptr += type->memSize;
  417. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  418. /* exchange the buffer and try to encode the same element once more */
  419. pos = oldpos;
  420. retval = exchangeBuffer();
  421. /* Repeat encoding of the same element */
  422. ptr -= type->memSize;
  423. --i;
  424. }
  425. }
  426. return retval;
  427. }
  428. static UA_StatusCode
  429. Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst,
  430. size_t *out_length, const UA_DataType *type) {
  431. /* decode the length */
  432. UA_Int32 signed_length;
  433. UA_StatusCode retval = Int32_decodeBinary(&signed_length);
  434. if(retval != UA_STATUSCODE_GOOD)
  435. return retval;
  436. /* check the length */
  437. if(signed_length <= 0) {
  438. *dst = NULL;
  439. if(signed_length == 0)
  440. *dst = UA_EMPTY_ARRAY_SENTINEL;
  441. return UA_STATUSCODE_GOOD;
  442. }
  443. size_t length = (size_t)signed_length;
  444. /* filter out arrays that can obviously not be parsed, because the message
  445. is too small */
  446. if(pos + ((type->memSize * length) / 32) > end)
  447. return UA_STATUSCODE_BADDECODINGERROR;
  448. /* allocate memory */
  449. *dst = UA_calloc(1, type->memSize * length);
  450. if(!*dst)
  451. return UA_STATUSCODE_BADOUTOFMEMORY;
  452. if(type->overlayable) {
  453. /* memcpy overlayable array */
  454. if(end < pos + (type->memSize * length)) {
  455. UA_free(*dst);
  456. *dst = NULL;
  457. return UA_STATUSCODE_BADDECODINGERROR;
  458. }
  459. memcpy(*dst, pos, type->memSize * length);
  460. pos += type->memSize * length;
  461. } else {
  462. /* Decode array members */
  463. uintptr_t ptr = (uintptr_t)*dst;
  464. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  465. for(size_t i = 0; i < length; ++i) {
  466. retval = decodeBinaryJumpTable[decode_index]((void*)ptr, type);
  467. if(retval != UA_STATUSCODE_GOOD) {
  468. UA_Array_delete(*dst, i, type);
  469. *dst = NULL;
  470. return retval;
  471. }
  472. ptr += type->memSize;
  473. }
  474. }
  475. *out_length = length;
  476. return UA_STATUSCODE_GOOD;
  477. }
  478. /*****************/
  479. /* Builtin Types */
  480. /*****************/
  481. static UA_StatusCode
  482. String_encodeBinary(UA_String const *src, const UA_DataType *_) {
  483. return Array_encodeBinary(src->data, src->length, &UA_TYPES[UA_TYPES_BYTE]);
  484. }
  485. static UA_StatusCode
  486. String_decodeBinary(UA_String *dst, const UA_DataType *_) {
  487. return Array_decodeBinary((void**)&dst->data, &dst->length, &UA_TYPES[UA_TYPES_BYTE]);
  488. }
  489. static UA_INLINE UA_StatusCode
  490. ByteString_encodeBinary(UA_ByteString const *src) {
  491. return String_encodeBinary((const UA_String*)src, NULL);
  492. }
  493. static UA_INLINE UA_StatusCode
  494. ByteString_decodeBinary(UA_ByteString *dst) {
  495. return String_decodeBinary((UA_ByteString*)dst, NULL);
  496. }
  497. /* Guid */
  498. static UA_StatusCode
  499. Guid_encodeBinary(UA_Guid const *src, const UA_DataType *_) {
  500. UA_StatusCode retval = UInt32_encodeBinary(&src->data1, NULL);
  501. retval |= UInt16_encodeBinary(&src->data2, NULL);
  502. retval |= UInt16_encodeBinary(&src->data3, NULL);
  503. if(pos + (8*sizeof(UA_Byte)) > end)
  504. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  505. memcpy(pos, src->data4, 8*sizeof(UA_Byte));
  506. pos += 8;
  507. return retval;
  508. }
  509. static UA_StatusCode
  510. Guid_decodeBinary(UA_Guid *dst, const UA_DataType *_) {
  511. UA_StatusCode retval = UInt32_decodeBinary(&dst->data1, NULL);
  512. retval |= UInt16_decodeBinary(&dst->data2, NULL);
  513. retval |= UInt16_decodeBinary(&dst->data3, NULL);
  514. if(pos + (8*sizeof(UA_Byte)) > end)
  515. return UA_STATUSCODE_BADDECODINGERROR;
  516. memcpy(dst->data4, pos, 8*sizeof(UA_Byte));
  517. pos += 8;
  518. return retval;
  519. }
  520. /* NodeId */
  521. #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
  522. #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
  523. #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
  524. static UA_StatusCode
  525. NodeId_encodeBinary(UA_NodeId const *src, const UA_DataType *_) {
  526. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  527. // temporary variables for endian-save code
  528. UA_Byte srcByte;
  529. UA_UInt16 srcUInt16;
  530. UA_UInt32 srcUInt32;
  531. switch (src->identifierType) {
  532. case UA_NODEIDTYPE_NUMERIC:
  533. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  534. srcByte = UA_NODEIDTYPE_NUMERIC_COMPLETE;
  535. retval |= Byte_encodeBinary(&srcByte, NULL);
  536. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  537. srcUInt32 = src->identifier.numeric;
  538. retval |= UInt32_encodeBinary(&srcUInt32, NULL);
  539. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  540. srcByte = UA_NODEIDTYPE_NUMERIC_FOURBYTE;
  541. retval |= Byte_encodeBinary(&srcByte, NULL);
  542. srcByte = (UA_Byte)src->namespaceIndex;
  543. srcUInt16 = (UA_UInt16)src->identifier.numeric;
  544. retval |= Byte_encodeBinary(&srcByte, NULL);
  545. retval |= UInt16_encodeBinary(&srcUInt16, NULL);
  546. } else {
  547. srcByte = UA_NODEIDTYPE_NUMERIC_TWOBYTE;
  548. retval |= Byte_encodeBinary(&srcByte, NULL);
  549. srcByte = (UA_Byte)src->identifier.numeric;
  550. retval |= Byte_encodeBinary(&srcByte, NULL);
  551. }
  552. break;
  553. case UA_NODEIDTYPE_STRING:
  554. srcByte = UA_NODEIDTYPE_STRING;
  555. retval |= Byte_encodeBinary(&srcByte, NULL);
  556. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  557. retval |= String_encodeBinary(&src->identifier.string, NULL);
  558. break;
  559. case UA_NODEIDTYPE_GUID:
  560. srcByte = UA_NODEIDTYPE_GUID;
  561. retval |= Byte_encodeBinary(&srcByte, NULL);
  562. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  563. retval |= Guid_encodeBinary(&src->identifier.guid, NULL);
  564. break;
  565. case UA_NODEIDTYPE_BYTESTRING:
  566. srcByte = UA_NODEIDTYPE_BYTESTRING;
  567. retval |= Byte_encodeBinary(&srcByte, NULL);
  568. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  569. retval |= ByteString_encodeBinary(&src->identifier.byteString);
  570. break;
  571. default:
  572. return UA_STATUSCODE_BADINTERNALERROR;
  573. }
  574. return retval;
  575. }
  576. static UA_StatusCode
  577. NodeId_decodeBinary(UA_NodeId *dst, const UA_DataType *_) {
  578. UA_Byte dstByte = 0, encodingByte = 0;
  579. UA_UInt16 dstUInt16 = 0;
  580. UA_StatusCode retval = Byte_decodeBinary(&encodingByte, NULL);
  581. if(retval != UA_STATUSCODE_GOOD)
  582. return retval;
  583. switch (encodingByte) {
  584. case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
  585. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  586. retval = Byte_decodeBinary(&dstByte, NULL);
  587. dst->identifier.numeric = dstByte;
  588. dst->namespaceIndex = 0;
  589. break;
  590. case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
  591. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  592. retval |= Byte_decodeBinary(&dstByte, NULL);
  593. dst->namespaceIndex = dstByte;
  594. retval |= UInt16_decodeBinary(&dstUInt16, NULL);
  595. dst->identifier.numeric = dstUInt16;
  596. break;
  597. case UA_NODEIDTYPE_NUMERIC_COMPLETE:
  598. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  599. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  600. retval |= UInt32_decodeBinary(&dst->identifier.numeric, NULL);
  601. break;
  602. case UA_NODEIDTYPE_STRING:
  603. dst->identifierType = UA_NODEIDTYPE_STRING;
  604. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  605. retval |= String_decodeBinary(&dst->identifier.string, NULL);
  606. break;
  607. case UA_NODEIDTYPE_GUID:
  608. dst->identifierType = UA_NODEIDTYPE_GUID;
  609. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  610. retval |= Guid_decodeBinary(&dst->identifier.guid, NULL);
  611. break;
  612. case UA_NODEIDTYPE_BYTESTRING:
  613. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  614. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  615. retval |= ByteString_decodeBinary(&dst->identifier.byteString);
  616. break;
  617. default:
  618. retval |= UA_STATUSCODE_BADINTERNALERROR;
  619. break;
  620. }
  621. return retval;
  622. }
  623. /* ExpandedNodeId */
  624. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
  625. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
  626. static UA_StatusCode
  627. ExpandedNodeId_encodeBinary(UA_ExpandedNodeId const *src, const UA_DataType *_) {
  628. if(pos >= end)
  629. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  630. UA_Byte *start = pos;
  631. UA_StatusCode retval = NodeId_encodeBinary(&src->nodeId, NULL);
  632. if(src->namespaceUri.length > 0) {
  633. retval |= String_encodeBinary(&src->namespaceUri, NULL);
  634. *start |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
  635. }
  636. if(src->serverIndex > 0) {
  637. retval |= UInt32_encodeBinary(&src->serverIndex, NULL);
  638. *start |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
  639. }
  640. return retval;
  641. }
  642. static UA_StatusCode
  643. ExpandedNodeId_decodeBinary(UA_ExpandedNodeId *dst, const UA_DataType *_) {
  644. if(pos >= end)
  645. return UA_STATUSCODE_BADDECODINGERROR;
  646. UA_Byte encodingByte = *pos;
  647. *pos = encodingByte & (UA_Byte)~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG | UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
  648. UA_StatusCode retval = NodeId_decodeBinary(&dst->nodeId, NULL);
  649. if(encodingByte & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
  650. dst->nodeId.namespaceIndex = 0;
  651. retval |= String_decodeBinary(&dst->namespaceUri, NULL);
  652. }
  653. if(encodingByte & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
  654. retval |= UInt32_decodeBinary(&dst->serverIndex, NULL);
  655. return retval;
  656. }
  657. /* LocalizedText */
  658. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
  659. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
  660. static UA_StatusCode
  661. LocalizedText_encodeBinary(UA_LocalizedText const *src, const UA_DataType *_) {
  662. UA_Byte encodingMask = 0;
  663. if(src->locale.data)
  664. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  665. if(src->text.data)
  666. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  667. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL);
  668. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  669. retval |= String_encodeBinary(&src->locale, NULL);
  670. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  671. retval |= String_encodeBinary(&src->text, NULL);
  672. return retval;
  673. }
  674. static UA_StatusCode
  675. LocalizedText_decodeBinary(UA_LocalizedText *dst, const UA_DataType *_) {
  676. UA_Byte encodingMask = 0;
  677. UA_StatusCode retval = Byte_decodeBinary(&encodingMask, NULL);
  678. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  679. retval |= String_decodeBinary(&dst->locale, NULL);
  680. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  681. retval |= String_decodeBinary(&dst->text, NULL);
  682. return retval;
  683. }
  684. static UA_StatusCode
  685. findDataTypeByBinary(const UA_NodeId *typeId, const UA_DataType **findtype) {
  686. for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
  687. if (UA_TYPES[i].binaryEncodingId == typeId->identifier.numeric) {
  688. *findtype = &UA_TYPES[i];
  689. return UA_STATUSCODE_GOOD;
  690. }
  691. }
  692. return UA_STATUSCODE_BADNODEIDUNKNOWN;
  693. }
  694. /* ExtensionObject */
  695. static UA_StatusCode
  696. ExtensionObject_encodeBinary(UA_ExtensionObject const *src, const UA_DataType *_) {
  697. UA_StatusCode retval;
  698. UA_Byte encoding = src->encoding;
  699. if(encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
  700. if(!src->content.decoded.type || !src->content.decoded.data)
  701. return UA_STATUSCODE_BADENCODINGERROR;
  702. UA_NodeId typeId = src->content.decoded.type->typeId;
  703. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  704. return UA_STATUSCODE_BADENCODINGERROR;
  705. typeId.identifier.numeric= src->content.decoded.type->binaryEncodingId;
  706. encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  707. retval = NodeId_encodeBinary(&typeId, NULL);
  708. retval |= Byte_encodeBinary(&encoding, NULL);
  709. UA_Byte *old_pos = pos; /* save the position to encode the length afterwards */
  710. pos += 4; /* jump over the length field */
  711. const UA_DataType *type = src->content.decoded.type;
  712. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  713. retval |= encodeBinaryJumpTable[encode_index](src->content.decoded.data, type);
  714. /* jump back, encode the length, jump back forward */
  715. UA_Int32 length = (UA_Int32)(((uintptr_t)pos - (uintptr_t)old_pos) / sizeof(UA_Byte)) - 4;
  716. UA_Byte *new_pos = pos;
  717. pos = old_pos;
  718. retval |= Int32_encodeBinary(&length);
  719. pos = new_pos;
  720. } else {
  721. retval = NodeId_encodeBinary(&src->content.encoded.typeId, NULL);
  722. retval |= Byte_encodeBinary(&encoding, NULL);
  723. switch (src->encoding) {
  724. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  725. break;
  726. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  727. case UA_EXTENSIONOBJECT_ENCODED_XML:
  728. retval |= ByteString_encodeBinary(&src->content.encoded.body);
  729. break;
  730. default:
  731. return UA_STATUSCODE_BADINTERNALERROR;
  732. }
  733. }
  734. return retval;
  735. }
  736. static UA_StatusCode
  737. ExtensionObject_decodeBinary(UA_ExtensionObject *dst, const UA_DataType *_) {
  738. UA_Byte encoding = 0;
  739. UA_NodeId typeId;
  740. UA_NodeId_init(&typeId);
  741. UA_StatusCode retval = NodeId_decodeBinary(&typeId, NULL);
  742. retval |= Byte_decodeBinary(&encoding, NULL);
  743. if(typeId.namespaceIndex != 0 || typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  744. retval = UA_STATUSCODE_BADDECODINGERROR;
  745. if(retval != UA_STATUSCODE_GOOD) {
  746. UA_NodeId_deleteMembers(&typeId);
  747. return retval;
  748. }
  749. if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
  750. dst->encoding = encoding;
  751. dst->content.encoded.typeId = typeId;
  752. dst->content.encoded.body = UA_BYTESTRING_NULL;
  753. } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
  754. dst->encoding = encoding;
  755. dst->content.encoded.typeId = typeId;
  756. retval = ByteString_decodeBinary(&dst->content.encoded.body);
  757. } else {
  758. /* try to decode the content */
  759. const UA_DataType *type = NULL;
  760. /* helping clang analyzer, typeId is numeric */
  761. UA_assert(typeId.identifier.byteString.data == NULL);
  762. UA_assert(typeId.identifier.string.data == NULL);
  763. findDataTypeByBinary(&typeId, &type);
  764. if(type) {
  765. pos += 4; /* jump over the length (todo: check if length matches) */
  766. dst->content.decoded.data = UA_new(type);
  767. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  768. if(dst->content.decoded.data) {
  769. dst->content.decoded.type = type;
  770. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  771. retval = decodeBinaryJumpTable[decode_index](dst->content.decoded.data, type);
  772. } else {
  773. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  774. }
  775. } else {
  776. retval = ByteString_decodeBinary(&dst->content.encoded.body);
  777. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  778. dst->content.encoded.typeId = typeId;
  779. }
  780. }
  781. return retval;
  782. }
  783. /* Variant */
  784. enum UA_VARIANT_ENCODINGMASKTYPE {
  785. UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F, // bits 0:5
  786. UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (0x01 << 6), // bit 6
  787. UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) // bit 7
  788. };
  789. static UA_StatusCode
  790. Variant_encodeBinary(UA_Variant const *src, const UA_DataType *_) {
  791. UA_Byte encodingByte = 0;
  792. if(!src->type)
  793. return Byte_encodeBinary(&encodingByte, NULL); /* empty variant */
  794. const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  795. const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  796. const UA_Boolean isBuiltin = src->type->builtin;
  797. /* Encode the encodingbyte */
  798. if(isArray) {
  799. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  800. if(hasDimensions)
  801. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  802. }
  803. if(isBuiltin) {
  804. UA_Byte t = (UA_Byte)(UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (src->type->typeIndex + 1));
  805. encodingByte |= t;
  806. } else {
  807. /* Non-builtin types are wrapped in an ExtensionObject */
  808. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte) 22;
  809. }
  810. UA_StatusCode retval = Byte_encodeBinary(&encodingByte, NULL);
  811. /* Encode the content */
  812. if(isBuiltin) {
  813. if(!isArray) {
  814. size_t encode_index = src->type->typeIndex;
  815. retval |= encodeBinaryJumpTable[encode_index](src->data, src->type);
  816. } else
  817. retval |= Array_encodeBinary(src->data, src->arrayLength, src->type);
  818. } else {
  819. /* Wrap not-builtin elements into an extensionobject */
  820. if(src->arrayDimensionsSize > UA_INT32_MAX)
  821. return UA_STATUSCODE_BADINTERNALERROR;
  822. size_t length = 1;
  823. if(isArray) {
  824. length = src->arrayLength;
  825. UA_Int32 encodedLength = (UA_Int32)src->arrayLength;
  826. retval |= Int32_encodeBinary(&encodedLength);
  827. }
  828. UA_ExtensionObject eo;
  829. UA_ExtensionObject_init(&eo);
  830. eo.encoding = UA_EXTENSIONOBJECT_DECODED;
  831. eo.content.decoded.type = src->type;
  832. const UA_UInt16 memSize = src->type->memSize;
  833. uintptr_t ptr = (uintptr_t)src->data;
  834. for(size_t i = 0; i < length && retval == UA_STATUSCODE_GOOD; ++i) {
  835. UA_Byte *oldpos = pos;
  836. eo.content.decoded.data = (void*)ptr;
  837. retval |= ExtensionObject_encodeBinary(&eo, NULL);
  838. ptr += memSize;
  839. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  840. /* exchange/send with the current buffer with chunking */
  841. pos = oldpos;
  842. retval = exchangeBuffer();
  843. /* encode the same element in the next iteration */
  844. --i;
  845. ptr -= memSize;
  846. }
  847. }
  848. }
  849. /* Encode the dimensions */
  850. if(hasDimensions)
  851. retval |= Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  852. &UA_TYPES[UA_TYPES_INT32]);
  853. return retval;
  854. }
  855. /* The resulting variant always has the storagetype UA_VARIANT_DATA. Currently,
  856. we only support ns0 types (todo: attach typedescriptions to datatypenodes) */
  857. static UA_StatusCode
  858. Variant_decodeBinary(UA_Variant *dst, const UA_DataType *_) {
  859. UA_Byte encodingByte;
  860. UA_StatusCode retval = Byte_decodeBinary(&encodingByte, NULL);
  861. if(retval != UA_STATUSCODE_GOOD)
  862. return retval;
  863. if(encodingByte == 0)
  864. return UA_STATUSCODE_GOOD; /* empty Variant (was already _inited) */
  865. UA_Boolean isArray = encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  866. size_t typeIndex = (size_t)((encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
  867. if(typeIndex > 24) /* the type must be builtin (maybe wrapped in an extensionobject) */
  868. return UA_STATUSCODE_BADDECODINGERROR;
  869. if(isArray) {
  870. /* an array */
  871. dst->type = &UA_TYPES[typeIndex]; /* Arrays of non-builtin types contain only ExtensionObjects */
  872. retval = Array_decodeBinary(&dst->data, &dst->arrayLength, dst->type);
  873. } else if (typeIndex != UA_TYPES_EXTENSIONOBJECT) {
  874. /* a builtin type */
  875. dst->type = &UA_TYPES[typeIndex];
  876. dst->data = UA_calloc(1, dst->type->memSize);
  877. if(!dst->data)
  878. return UA_STATUSCODE_BADOUTOFMEMORY;
  879. size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  880. retval = decodeBinaryJumpTable[decode_index](dst->data, dst->type);
  881. // dst->arrayLength = 0; /* is null already in an initialized type */
  882. } else {
  883. /* a single extensionobject */
  884. UA_Byte *old_pos = pos; /* save the beginning of the extensionobject */
  885. UA_NodeId typeId;
  886. UA_NodeId_init(&typeId);
  887. retval = NodeId_decodeBinary(&typeId, NULL);
  888. if(retval != UA_STATUSCODE_GOOD)
  889. return retval;
  890. UA_Byte eo_encoding;
  891. retval = Byte_decodeBinary(&eo_encoding, NULL);
  892. if(retval != UA_STATUSCODE_GOOD) {
  893. UA_NodeId_deleteMembers(&typeId);
  894. return retval;
  895. }
  896. /* search for the datatype. use extensionobject if nothing is found */
  897. dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
  898. if(typeId.namespaceIndex == 0 && typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
  899. eo_encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
  900. UA_assert(typeId.identifier.byteString.data == NULL); /* for clang analyzer <= 3.7 */
  901. if(findDataTypeByBinary(&typeId, &dst->type) == UA_STATUSCODE_GOOD)
  902. pos += 4; /* jump over the length (todo: check if length matches) */
  903. else
  904. pos = old_pos; /* jump back and decode as extensionobject */
  905. } else {
  906. pos = old_pos; /* jump back and decode as extensionobject */
  907. UA_NodeId_deleteMembers(&typeId); /* found nodeids are always numerical */
  908. }
  909. /* decode the type */
  910. dst->data = UA_calloc(1, dst->type->memSize);
  911. if(!dst->data)
  912. return UA_STATUSCODE_BADOUTOFMEMORY;
  913. size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  914. retval = decodeBinaryJumpTable[decode_index](dst->data, dst->type);
  915. if(retval != UA_STATUSCODE_GOOD) {
  916. UA_free(dst->data);
  917. dst->data = NULL;
  918. }
  919. }
  920. /* array dimensions */
  921. if(isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS))
  922. retval |= Array_decodeBinary((void**)&dst->arrayDimensions,
  923. &dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
  924. return retval;
  925. }
  926. /* DataValue */
  927. static UA_StatusCode
  928. DataValue_encodeBinary(UA_DataValue const *src, const UA_DataType *_) {
  929. UA_Byte encodingMask = (UA_Byte)
  930. (src->hasValue | (src->hasStatus << 1) | (src->hasSourceTimestamp << 2) |
  931. (src->hasServerTimestamp << 3) | (src->hasSourcePicoseconds << 4) |
  932. (src->hasServerPicoseconds << 5));
  933. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL);
  934. if(src->hasValue)
  935. retval |= Variant_encodeBinary(&src->value, NULL);
  936. if(src->hasStatus)
  937. retval |= StatusCode_encodeBinary(&src->status);
  938. if(src->hasSourceTimestamp)
  939. retval |= DateTime_encodeBinary(&src->sourceTimestamp);
  940. if(src->hasSourcePicoseconds)
  941. retval |= UInt16_encodeBinary(&src->sourcePicoseconds, NULL);
  942. if(src->hasServerTimestamp)
  943. retval |= DateTime_encodeBinary(&src->serverTimestamp);
  944. if(src->hasServerPicoseconds)
  945. retval |= UInt16_encodeBinary(&src->serverPicoseconds, NULL);
  946. return retval;
  947. }
  948. #define MAX_PICO_SECONDS 9999
  949. static UA_StatusCode
  950. DataValue_decodeBinary(UA_DataValue *dst, const UA_DataType *_) {
  951. UA_Byte encodingMask;
  952. UA_StatusCode retval = Byte_decodeBinary(&encodingMask, NULL);
  953. if(retval != UA_STATUSCODE_GOOD)
  954. return retval;
  955. if(encodingMask & 0x01) {
  956. dst->hasValue = true;
  957. retval |= Variant_decodeBinary(&dst->value, NULL);
  958. }
  959. if(encodingMask & 0x02) {
  960. dst->hasStatus = true;
  961. retval |= StatusCode_decodeBinary(&dst->status);
  962. }
  963. if(encodingMask & 0x04) {
  964. dst->hasSourceTimestamp = true;
  965. retval |= DateTime_decodeBinary(&dst->sourceTimestamp);
  966. }
  967. if(encodingMask & 0x10) {
  968. dst->hasSourcePicoseconds = true;
  969. retval |= UInt16_decodeBinary(&dst->sourcePicoseconds, NULL);
  970. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  971. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  972. }
  973. if(encodingMask & 0x08) {
  974. dst->hasServerTimestamp = true;
  975. retval |= DateTime_decodeBinary(&dst->serverTimestamp);
  976. }
  977. if(encodingMask & 0x20) {
  978. dst->hasServerPicoseconds = true;
  979. retval |= UInt16_decodeBinary(&dst->serverPicoseconds, NULL);
  980. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  981. dst->serverPicoseconds = MAX_PICO_SECONDS;
  982. }
  983. return retval;
  984. }
  985. /* DiagnosticInfo */
  986. static UA_StatusCode
  987. DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, const UA_DataType *_) {
  988. UA_Byte encodingMask = (UA_Byte)
  989. (src->hasSymbolicId | (src->hasNamespaceUri << 1) |
  990. (src->hasLocalizedText << 2) | (src->hasLocale << 3) |
  991. (src->hasAdditionalInfo << 4) | (src->hasInnerDiagnosticInfo << 5));
  992. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL);
  993. if(src->hasSymbolicId)
  994. retval |= Int32_encodeBinary(&src->symbolicId);
  995. if(src->hasNamespaceUri)
  996. retval |= Int32_encodeBinary(&src->namespaceUri);
  997. if(src->hasLocalizedText)
  998. retval |= Int32_encodeBinary(&src->localizedText);
  999. if(src->hasLocale)
  1000. retval |= Int32_encodeBinary(&src->locale);
  1001. if(src->hasAdditionalInfo)
  1002. retval |= String_encodeBinary(&src->additionalInfo, NULL);
  1003. if(src->hasInnerStatusCode)
  1004. retval |= StatusCode_encodeBinary(&src->innerStatusCode);
  1005. if(src->hasInnerDiagnosticInfo)
  1006. retval |= DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, NULL);
  1007. return retval;
  1008. }
  1009. static UA_StatusCode
  1010. DiagnosticInfo_decodeBinary(UA_DiagnosticInfo *dst, const UA_DataType *_) {
  1011. UA_Byte encodingMask;
  1012. UA_StatusCode retval = Byte_decodeBinary(&encodingMask, NULL);
  1013. if(retval != UA_STATUSCODE_GOOD)
  1014. return retval;
  1015. if(encodingMask & 0x01) {
  1016. dst->hasSymbolicId = true;
  1017. retval |= Int32_decodeBinary(&dst->symbolicId);
  1018. }
  1019. if(encodingMask & 0x02) {
  1020. dst->hasNamespaceUri = true;
  1021. retval |= Int32_decodeBinary(&dst->namespaceUri);
  1022. }
  1023. if(encodingMask & 0x04) {
  1024. dst->hasLocalizedText = true;
  1025. retval |= Int32_decodeBinary(&dst->localizedText);
  1026. }
  1027. if(encodingMask & 0x08) {
  1028. dst->hasLocale = true;
  1029. retval |= Int32_decodeBinary(&dst->locale);
  1030. }
  1031. if(encodingMask & 0x10) {
  1032. dst->hasAdditionalInfo = true;
  1033. retval |= String_decodeBinary(&dst->additionalInfo, NULL);
  1034. }
  1035. if(encodingMask & 0x20) {
  1036. dst->hasInnerStatusCode = true;
  1037. retval |= StatusCode_decodeBinary(&dst->innerStatusCode);
  1038. }
  1039. if(encodingMask & 0x40) {
  1040. /* innerDiagnosticInfo is allocated on the heap */
  1041. dst->innerDiagnosticInfo = UA_calloc(1, sizeof(UA_DiagnosticInfo));
  1042. if(!dst->innerDiagnosticInfo)
  1043. return UA_STATUSCODE_BADOUTOFMEMORY;
  1044. dst->hasInnerDiagnosticInfo = true;
  1045. retval |= DiagnosticInfo_decodeBinary(dst->innerDiagnosticInfo, NULL);
  1046. }
  1047. return retval;
  1048. }
  1049. /********************/
  1050. /* Structured Types */
  1051. /********************/
  1052. static UA_StatusCode
  1053. UA_encodeBinaryInternal(const void *src, const UA_DataType *type);
  1054. static UA_StatusCode
  1055. UA_decodeBinaryInternal(void *dst, const UA_DataType *type);
  1056. static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1057. (UA_encodeBinarySignature)Boolean_encodeBinary,
  1058. (UA_encodeBinarySignature)Byte_encodeBinary, // SByte
  1059. (UA_encodeBinarySignature)Byte_encodeBinary,
  1060. (UA_encodeBinarySignature)UInt16_encodeBinary, // Int16
  1061. (UA_encodeBinarySignature)UInt16_encodeBinary,
  1062. (UA_encodeBinarySignature)UInt32_encodeBinary, // Int32
  1063. (UA_encodeBinarySignature)UInt32_encodeBinary,
  1064. (UA_encodeBinarySignature)UInt64_encodeBinary, // Int64
  1065. (UA_encodeBinarySignature)UInt64_encodeBinary,
  1066. (UA_encodeBinarySignature)Float_encodeBinary,
  1067. (UA_encodeBinarySignature)Double_encodeBinary,
  1068. (UA_encodeBinarySignature)String_encodeBinary,
  1069. (UA_encodeBinarySignature)UInt64_encodeBinary, // DateTime
  1070. (UA_encodeBinarySignature)Guid_encodeBinary,
  1071. (UA_encodeBinarySignature)String_encodeBinary, // ByteString
  1072. (UA_encodeBinarySignature)String_encodeBinary, // XmlElement
  1073. (UA_encodeBinarySignature)NodeId_encodeBinary,
  1074. (UA_encodeBinarySignature)ExpandedNodeId_encodeBinary,
  1075. (UA_encodeBinarySignature)UInt32_encodeBinary, // StatusCode
  1076. (UA_encodeBinarySignature)UA_encodeBinaryInternal, // QualifiedName
  1077. (UA_encodeBinarySignature)LocalizedText_encodeBinary,
  1078. (UA_encodeBinarySignature)ExtensionObject_encodeBinary,
  1079. (UA_encodeBinarySignature)DataValue_encodeBinary,
  1080. (UA_encodeBinarySignature)Variant_encodeBinary,
  1081. (UA_encodeBinarySignature)DiagnosticInfo_encodeBinary,
  1082. (UA_encodeBinarySignature)UA_encodeBinaryInternal,
  1083. };
  1084. static UA_StatusCode
  1085. UA_encodeBinaryInternal(const void *src, const UA_DataType *type) {
  1086. uintptr_t ptr = (uintptr_t)src;
  1087. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1088. UA_Byte membersSize = type->membersSize;
  1089. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1090. for(size_t i = 0; i < membersSize && retval == UA_STATUSCODE_GOOD; ++i) {
  1091. const UA_DataTypeMember *member = &type->members[i];
  1092. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1093. if(!member->isArray) {
  1094. ptr += member->padding;
  1095. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1096. size_t memSize = membertype->memSize;
  1097. UA_Byte *oldpos = pos;
  1098. retval |= encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
  1099. ptr += memSize;
  1100. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  1101. /* exchange/send the buffer and try to encode the same type once more */
  1102. pos = oldpos;
  1103. retval = exchangeBuffer();
  1104. /* re-encode the same member on the new buffer */
  1105. ptr -= member->padding + memSize;
  1106. --i;
  1107. }
  1108. } else {
  1109. ptr += member->padding;
  1110. const size_t length = *((const size_t*)ptr);
  1111. ptr += sizeof(size_t);
  1112. retval |= Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1113. ptr += sizeof(void*);
  1114. }
  1115. }
  1116. return retval;
  1117. }
  1118. UA_StatusCode
  1119. UA_encodeBinary(const void *src, const UA_DataType *type,
  1120. UA_exchangeEncodeBuffer callback, void *handle,
  1121. UA_ByteString *dst, size_t *offset) {
  1122. /* Set the (thread-local) position and end pointers to save function
  1123. arguments */
  1124. pos = &dst->data[*offset];
  1125. end = &dst->data[dst->length];
  1126. /* Set the (thread-local) callbacks where the buffer is exchanged and the
  1127. current chunk sent out */
  1128. encodeBuf = dst;
  1129. exchangeBufferCallback = callback;
  1130. exchangeBufferCallbackHandle = handle;
  1131. /* Encode and clean up */
  1132. UA_StatusCode retval = UA_encodeBinaryInternal(src, type);
  1133. *offset = (size_t)(pos - dst->data) / sizeof(UA_Byte);
  1134. return retval;
  1135. }
  1136. static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1137. (UA_decodeBinarySignature)Boolean_decodeBinary,
  1138. (UA_decodeBinarySignature)Byte_decodeBinary, // SByte
  1139. (UA_decodeBinarySignature)Byte_decodeBinary,
  1140. (UA_decodeBinarySignature)UInt16_decodeBinary, // Int16
  1141. (UA_decodeBinarySignature)UInt16_decodeBinary,
  1142. (UA_decodeBinarySignature)UInt32_decodeBinary, // Int32
  1143. (UA_decodeBinarySignature)UInt32_decodeBinary,
  1144. (UA_decodeBinarySignature)UInt64_decodeBinary, // Int64
  1145. (UA_decodeBinarySignature)UInt64_decodeBinary,
  1146. (UA_decodeBinarySignature)Float_decodeBinary,
  1147. (UA_decodeBinarySignature)Double_decodeBinary,
  1148. (UA_decodeBinarySignature)String_decodeBinary,
  1149. (UA_decodeBinarySignature)UInt64_decodeBinary, // DateTime
  1150. (UA_decodeBinarySignature)Guid_decodeBinary,
  1151. (UA_decodeBinarySignature)String_decodeBinary, // ByteString
  1152. (UA_decodeBinarySignature)String_decodeBinary, // XmlElement
  1153. (UA_decodeBinarySignature)NodeId_decodeBinary,
  1154. (UA_decodeBinarySignature)ExpandedNodeId_decodeBinary,
  1155. (UA_decodeBinarySignature)UInt32_decodeBinary, // StatusCode
  1156. (UA_decodeBinarySignature)UA_decodeBinaryInternal, // QualifiedName
  1157. (UA_decodeBinarySignature)LocalizedText_decodeBinary,
  1158. (UA_decodeBinarySignature)ExtensionObject_decodeBinary,
  1159. (UA_decodeBinarySignature)DataValue_decodeBinary,
  1160. (UA_decodeBinarySignature)Variant_decodeBinary,
  1161. (UA_decodeBinarySignature)DiagnosticInfo_decodeBinary,
  1162. (UA_decodeBinarySignature)UA_decodeBinaryInternal
  1163. };
  1164. static UA_StatusCode
  1165. UA_decodeBinaryInternal(void *dst, const UA_DataType *type) {
  1166. uintptr_t ptr = (uintptr_t)dst;
  1167. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1168. UA_Byte membersSize = type->membersSize;
  1169. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1170. for(size_t i = 0; i < membersSize; ++i) {
  1171. const UA_DataTypeMember *member = &type->members[i];
  1172. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1173. if(!member->isArray) {
  1174. ptr += member->padding;
  1175. size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1176. size_t memSize = membertype->memSize;
  1177. retval |= decodeBinaryJumpTable[fi]((void *UA_RESTRICT)ptr, membertype);
  1178. ptr += memSize;
  1179. } else {
  1180. ptr += member->padding;
  1181. size_t *length = (size_t*)ptr;
  1182. ptr += sizeof(size_t);
  1183. retval |= Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, membertype);
  1184. ptr += sizeof(void*);
  1185. }
  1186. }
  1187. return retval;
  1188. }
  1189. UA_StatusCode
  1190. UA_decodeBinary(const UA_ByteString *src, size_t *offset,
  1191. void *dst, const UA_DataType *type) {
  1192. /* Initialize the destination */
  1193. memset(dst, 0, type->memSize);
  1194. /* Set the (thread-local) position and end pointers to save function
  1195. arguments */
  1196. pos = &src->data[*offset];
  1197. end = &src->data[src->length];
  1198. /* Decode */
  1199. UA_StatusCode retval = UA_decodeBinaryInternal(dst, type);
  1200. /* Clean up */
  1201. if(retval == UA_STATUSCODE_GOOD)
  1202. *offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
  1203. else
  1204. UA_deleteMembers(dst, type);
  1205. return retval;
  1206. }
  1207. /******************/
  1208. /* CalcSizeBinary */
  1209. /******************/
  1210. static size_t
  1211. Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
  1212. size_t s = 4; // length
  1213. if(type->overlayable) {
  1214. s += type->memSize * length;
  1215. return s;
  1216. }
  1217. uintptr_t ptr = (uintptr_t)src;
  1218. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1219. for(size_t i = 0; i < length; ++i) {
  1220. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, type);
  1221. ptr += type->memSize;
  1222. }
  1223. return s;
  1224. }
  1225. static size_t
  1226. calcSizeBinaryMemSize(const void *UA_RESTRICT p, const UA_DataType *type) {
  1227. return type->memSize;
  1228. }
  1229. static size_t
  1230. String_calcSizeBinary(const UA_String *UA_RESTRICT p, const UA_DataType *_) {
  1231. return 4 + p->length;
  1232. }
  1233. static size_t
  1234. Guid_calcSizeBinary(const UA_Guid *UA_RESTRICT p, const UA_DataType *_) {
  1235. return 16;
  1236. }
  1237. static size_t
  1238. NodeId_calcSizeBinary(const UA_NodeId *UA_RESTRICT src, const UA_DataType *_) {
  1239. size_t s = 1; // encoding byte
  1240. switch (src->identifierType) {
  1241. case UA_NODEIDTYPE_NUMERIC:
  1242. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  1243. s += 6;
  1244. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  1245. s += 3;
  1246. } else {
  1247. s += 1;
  1248. }
  1249. break;
  1250. case UA_NODEIDTYPE_BYTESTRING:
  1251. case UA_NODEIDTYPE_STRING:
  1252. s += 2;
  1253. s += String_calcSizeBinary(&src->identifier.string, NULL);
  1254. break;
  1255. case UA_NODEIDTYPE_GUID:
  1256. s += 18;
  1257. break;
  1258. default:
  1259. return 0;
  1260. }
  1261. return s;
  1262. }
  1263. static size_t
  1264. ExpandedNodeId_calcSizeBinary(const UA_ExpandedNodeId *src, const UA_DataType *_) {
  1265. size_t s = NodeId_calcSizeBinary(&src->nodeId, NULL);
  1266. if(src->namespaceUri.length > 0)
  1267. s += String_calcSizeBinary(&src->namespaceUri, NULL);
  1268. if(src->serverIndex > 0)
  1269. s += 4;
  1270. return s;
  1271. }
  1272. static size_t
  1273. LocalizedText_calcSizeBinary(const UA_LocalizedText *src, UA_DataType *_) {
  1274. size_t s = 1; // encoding byte
  1275. if(src->locale.data)
  1276. s += String_calcSizeBinary(&src->locale, NULL);
  1277. if(src->text.data)
  1278. s += String_calcSizeBinary(&src->text, NULL);
  1279. return s;
  1280. }
  1281. static size_t
  1282. ExtensionObject_calcSizeBinary(const UA_ExtensionObject *src, UA_DataType *_) {
  1283. size_t s = 1; // encoding byte
  1284. if(src->encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
  1285. if(!src->content.decoded.type || !src->content.decoded.data)
  1286. return 0;
  1287. if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1288. return 0;
  1289. s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL);
  1290. s += 4; // length
  1291. const UA_DataType *type = src->content.decoded.type;
  1292. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1293. s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, type);
  1294. } else {
  1295. s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
  1296. switch (src->encoding) {
  1297. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  1298. break;
  1299. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  1300. case UA_EXTENSIONOBJECT_ENCODED_XML:
  1301. s += String_calcSizeBinary(&src->content.encoded.body, NULL);
  1302. break;
  1303. default:
  1304. return 0;
  1305. }
  1306. }
  1307. return s;
  1308. }
  1309. static size_t
  1310. Variant_calcSizeBinary(UA_Variant const *src, UA_DataType *_) {
  1311. size_t s = 1; /* encoding byte */
  1312. if(!src->type)
  1313. return s;
  1314. UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  1315. UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  1316. UA_Boolean isBuiltin = src->type->builtin;
  1317. UA_NodeId typeId;
  1318. UA_NodeId_init(&typeId);
  1319. size_t encode_index = src->type->typeIndex;
  1320. if(!isBuiltin) {
  1321. encode_index = UA_BUILTIN_TYPES_COUNT;
  1322. typeId = src->type->typeId;
  1323. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1324. return 0;
  1325. }
  1326. size_t length = src->arrayLength;
  1327. if(isArray)
  1328. s += 4;
  1329. else
  1330. length = 1;
  1331. uintptr_t ptr = (uintptr_t)src->data;
  1332. size_t memSize = src->type->memSize;
  1333. for(size_t i = 0; i < length; ++i) {
  1334. if(!isBuiltin) {
  1335. /* The type is wrapped inside an extensionobject */
  1336. s += NodeId_calcSizeBinary(&typeId, NULL);
  1337. s += 1 + 4; // encoding byte + length
  1338. }
  1339. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, src->type);
  1340. ptr += memSize;
  1341. }
  1342. if(hasDimensions)
  1343. s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  1344. &UA_TYPES[UA_TYPES_INT32]);
  1345. return s;
  1346. }
  1347. static size_t
  1348. DataValue_calcSizeBinary(const UA_DataValue *src, UA_DataType *_) {
  1349. size_t s = 1; // encoding byte
  1350. if(src->hasValue)
  1351. s += Variant_calcSizeBinary(&src->value, NULL);
  1352. if(src->hasStatus)
  1353. s += 4;
  1354. if(src->hasSourceTimestamp)
  1355. s += 8;
  1356. if(src->hasSourcePicoseconds)
  1357. s += 2;
  1358. if(src->hasServerTimestamp)
  1359. s += 8;
  1360. if(src->hasServerPicoseconds)
  1361. s += 2;
  1362. return s;
  1363. }
  1364. static size_t
  1365. DiagnosticInfo_calcSizeBinary(const UA_DiagnosticInfo *src, UA_DataType *_) {
  1366. size_t s = 1; // encoding byte
  1367. if(src->hasSymbolicId)
  1368. s += 4;
  1369. if(src->hasNamespaceUri)
  1370. s += 4;
  1371. if(src->hasLocalizedText)
  1372. s += 4;
  1373. if(src->hasLocale)
  1374. s += 4;
  1375. if(src->hasAdditionalInfo)
  1376. s += String_calcSizeBinary(&src->additionalInfo, NULL);
  1377. if(src->hasInnerStatusCode)
  1378. s += 4;
  1379. if(src->hasInnerDiagnosticInfo)
  1380. s += DiagnosticInfo_calcSizeBinary(src->innerDiagnosticInfo, NULL);
  1381. return s;
  1382. }
  1383. static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1384. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Boolean
  1385. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Byte
  1386. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1387. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int16
  1388. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1389. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int32
  1390. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1391. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int64
  1392. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1393. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Float
  1394. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Double
  1395. (UA_calcSizeBinarySignature)String_calcSizeBinary,
  1396. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // DateTime
  1397. (UA_calcSizeBinarySignature)Guid_calcSizeBinary,
  1398. (UA_calcSizeBinarySignature)String_calcSizeBinary, // ByteString
  1399. (UA_calcSizeBinarySignature)String_calcSizeBinary, // XmlElement
  1400. (UA_calcSizeBinarySignature)NodeId_calcSizeBinary,
  1401. (UA_calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
  1402. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // StatusCode
  1403. (UA_calcSizeBinarySignature)UA_calcSizeBinary, // QualifiedName
  1404. (UA_calcSizeBinarySignature)LocalizedText_calcSizeBinary,
  1405. (UA_calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
  1406. (UA_calcSizeBinarySignature)DataValue_calcSizeBinary,
  1407. (UA_calcSizeBinarySignature)Variant_calcSizeBinary,
  1408. (UA_calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
  1409. (UA_calcSizeBinarySignature)UA_calcSizeBinary
  1410. };
  1411. size_t
  1412. UA_calcSizeBinary(void *p, const UA_DataType *type) {
  1413. size_t s = 0;
  1414. uintptr_t ptr = (uintptr_t)p;
  1415. UA_Byte membersSize = type->membersSize;
  1416. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1417. for(size_t i = 0; i < membersSize; ++i) {
  1418. const UA_DataTypeMember *member = &type->members[i];
  1419. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1420. if(!member->isArray) {
  1421. ptr += member->padding;
  1422. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1423. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
  1424. ptr += membertype->memSize;
  1425. } else {
  1426. ptr += member->padding;
  1427. const size_t length = *((const size_t*)ptr);
  1428. ptr += sizeof(size_t);
  1429. s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1430. ptr += sizeof(void*);
  1431. }
  1432. }
  1433. return s;
  1434. }