ua_types_encoding_binary.c 60 KB

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